如何在运行时(Runtime)获得泛型的真正类型
前言
由于Java 的类型擦除机制,在编译时泛型都被转为了Object,例如List<String>
经过编译之后将变为类型 List。可以通过以下的方式再运行时获得泛型的真正类型
泛型如何获得具体类型
List 例子如下
来自:https://stackoverflow.com/questions/1942644/get-generic-type-of-java-util-list
package test;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
public class Test {
List<String> stringList = new ArrayList<String>();
List<Integer> integerList = new ArrayList<Integer>();
public static void main(String... args) throws Exception {
Field stringListField = Test.class.getDeclaredField("stringList");
ParameterizedType stringListType = (ParameterizedType) stringListField.getGenericType();
Class<?> stringListClass = (Class<?>) stringListType.getActualTypeArguments()[0];
System.out.println(stringListClass); // class java.lang.String.
Field integerListField = Test.class.getDeclaredField("integerList");
ParameterizedType integerListType = (ParameterizedType) integerListField.getGenericType();
Class<?> integerListClass = (Class<?>) integerListType.getActualTypeArguments()[0];
System.out.println(integerListClass); // class java.lang.Integer.
}
}
Map 的例子如下
来自:https://stackoverflow.com/questions/3687766/how-to-get-value-type-of-a-map-in-java
import java.lang.reflect.*;
import java.util.*;
public class Generic {
private Map<String, Number> map = new HashMap<String, Number>();
public static void main(String[] args) {
try {
ParameterizedType pt = (ParameterizedType)Generic.class.getDeclaredField("map").getGenericType();
for(Type type : pt.getActualTypeArguments()) {
System.out.println(type.toString());
}
} catch(NoSuchFieldException e) {
e.printStackTrace();
}
}
}
实际二者都利用的反射,都是基于 java.lang.reflect.ParameterizedType
jackson 中如何反序列化泛型
jackson 中将JSON 转为Map 的可以通过如下代码实现,方式一:
ObjectMapper mapper = new ObjectMapper();
String json = "{\"name\":\"mkyong\", \"age\":29}";
Map map = mapper.readValue(json, Map.class);
Object name = map.get("name")
上述只是指定了是 Map 类型,但是没有指定Map里边存放的数据是什么类型,所以得到结果之后还需要对 Object name
做一次强制类型转换才能够使用。
可以使用方式二,告知实际 Map
中存放的对象,从而得到正确的类型,代码如下所示:
ObjectMapper mapper = new ObjectMapper();
String json = "{\"name\":\"mkyong\", \"age\":29}";
Map<String, Object> map = mapper.readValue(json, new TypeReference<Map<String, String>>(){});
TypeReference
实际上就是告诉了 ObjectMapper
反序列化时要转换的真正类型是什么。
TypeReference 源码
package com.fasterxml.jackson.core.type;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public abstract class TypeReference<T> implements Comparable<TypeReference<T>> {
protected final Type _type;
protected TypeReference() {
Type superClass = this.getClass().getGenericSuperclass();
if (superClass instanceof Class) {
throw new IllegalArgumentException("Internal error: TypeReference constructed without actual type information");
} else {
this._type = ((ParameterizedType)superClass).getActualTypeArguments()[0];
}
}
public Type getType() {
return this._type;
}
public int compareTo(TypeReference<T> o) {
return 0;
}
}
有一个 protected
的构造器,所以在使用的时候默认就会执行该构造器,上述方案二将会走到分支代码 this._type = ((ParameterizedType)superClass).getActualTypeArguments()[0];
,从而 getType
能够得到正确的类型。实际上也是根据 ParameterizedType
获得真正的类型。
通过 TypeReference 获得真正类型
代码类似如下,最后得到的 tmpType1
是 Class
类型,就能够基于它其他的操作了。
TypeReference<Map<String, Test>> typeReference = new TypeReference<Map<String, Test>>(){};
ParameterizedType type = (ParameterizedType)typeReference.getType();
for (Type tmpType : type.getActualTypeArguments()) {
Class<?> tmpType1 = (Class<?>) tmpType;
System.out.println(tmpType1);
}
欢迎转载,但请注明本文链接,谢谢你。
2018.10.28 20:47
如何在运行时(Runtime)获得泛型的真正类型的更多相关文章
- iOS运行时 -- Runtime(摘抄自网络)
运行时(iOS) 一.什么是运行时(Runtime)? 运行时是苹果提供的纯C语言的开发库(运行时是一种非常牛逼.开发中经常用到的底层技术) 二.运行时的作用? 能获得某个类的所有成员变量 能获得某个 ...
- 为什么说OC是运行时语言?什么是动态类型、动态绑定、动态加载?
转载:https://www.cnblogs.com/dxb123456/p/5525343.html 动态: 主要是将数据类型的确定由编译时,推迟到了运行时. 这个问题其实浅涉及到两个概念,运行时和 ...
- RTTI (Run-Time Type Identification,通过运行时类型识别) 转
参考一: RTTI(Run-Time Type Identification,通过运行时类型识别)程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型. RTTI提供了以下两个 ...
- java运行时获得泛型类型
引言 众所周知,java泛型最重要的特征是泛型擦除,所有泛型在编译时会转换成Object所以在java中运行时无法获得泛型的类型. 但是其实以上的规则是针对方法的内部变量的,如果是其他形式的泛型其实是 ...
- Java运行时环境---内存划分
背景:听说Java运行时环境的内存划分是挺进BAT的必经之路. 内存划分: Java程序内存的划分是交由JVM执行的,而不像C语言那样需要程序员自己买单(C语言需要程序员为每一个new操作去配对del ...
- 【转】Java运行时数据区简介及堆与栈的区别
理解JVM运行时的数据区是Java编程中的进阶部分.我们在开发中都遇到过一个很头疼的问题就是OutOfMemoryError(内存溢出错误),但是如果我们了解JVM的内部实现和其运行时的数据区的工作机 ...
- [Asp.net 5] Localization-Asp.net运行时多语言
本节介绍的是Microsoft.AspNet.Localization工程.该工程是运行在Asp.net 5环境中的运行时多语言设置. ASP.net 5中间件技术 在新的Asp.net 5中,可以将 ...
- 《Effective C#》读书笔记-1.C# 语言习惯-2.使用运行时常量(readonly)而不是编译时常量(const)
概念 编译时 编译时顾名思义就是正在编译的时候.那啥叫编译呢?就是编译器帮你把源代码翻译成机器能识别的代码.(当然只是一般意义上这么说,实际上可能只是翻译成某个中间状态的语言.比如Java只有JVM识 ...
- [二]Java虚拟机 jvm内存结构 运行时数据内存 class文件与jvm内存结构的映射 jvm数据类型 虚拟机栈 方法区 堆 含义
前言简介 class文件是源代码经过编译后的一种平台中立的格式 里面包含了虚拟机运行所需要的所有信息,相当于 JVM的机器语言 JVM全称是Java Virtual Machine ,既然是虚拟机, ...
随机推荐
- ELK快速部署及使用~
Elastic Stack 开发人员不能登陆线上服务器查看详细日志 各个系统都有日志,日志数据分散难以查找 日志数据量大,查询速度慢,或者数据不够实时 官网地址:https://www.elastic ...
- 读《Tooth-Marked Tongue Recgnition Using Multiple Instance Learning and CNN Features》
本人 组会汇报的一篇关于齿痕舌判定的文章,贴上PPT 涉及多示例学习和神经网络方面知识. 准确率有待提高哈哈.
- ZYNQ DMA驱动及测试分析
之前没有接触过DMA驱动.不了解它的原理,稍作学习先总结下dma驱动步骤: 1. 申请DMA中断. 2. 申请内存空间作为src和dts的空间. 3. 注册设备注册节点 4. 将申请到的src和dst ...
- Public_1.bat
:: targetset targetFileName=Public_2set targetPath=./:: sourceset sourceFileName=Public_1@echo ui ru ...
- .net实现网易云音乐下载
客户端版的网易云音乐下载是需要vip的,网页版的虽然可以通过调试工具找到下载链接,但是用起来不是很方便,通过调试工具观察请求发现请求参数都是加密的,比如搜索歌曲的请求参数: 这个加密的实现肯定是写在j ...
- caffe源码阅读
参考网址:https://www.cnblogs.com/louyihang-loves-baiyan/p/5149628.html 1.caffe代码层次熟悉blob,layer,net,solve ...
- 使用eclipse新建一个c项目
一.打开eclipse并新建项目 1.快捷键:字体放大:Ctrl+Shift+“+” 字体缩小:Ctrl+“-”
- C# [LINQ] Linq Expression 获取多格式文件
using System; using System.IO; using System.Linq; using System.Linq.Expressions; internal static str ...
- 基于mykernel完成多进程的简单内核
学号351 原创作品转载请注明出处 + https://github.com/mengning/linuxkernel/ mykernel简介 mykernel是由孟宁老师建立的一个用于开发您自己的操 ...
- 关于Apache的配置方法和步骤
一.下载.安装和卸载 网址:https://httpd.apache.org/docs/current/platform/windows.html#down 点击ApacheHaus,在里面下载任何版 ...