前言

由于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 获得真正类型

代码类似如下,最后得到的 tmpType1Class 类型,就能够基于它其他的操作了。

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)获得泛型的真正类型的更多相关文章

  1. iOS运行时 -- Runtime(摘抄自网络)

    运行时(iOS) 一.什么是运行时(Runtime)? 运行时是苹果提供的纯C语言的开发库(运行时是一种非常牛逼.开发中经常用到的底层技术) 二.运行时的作用? 能获得某个类的所有成员变量 能获得某个 ...

  2. 为什么说OC是运行时语言?什么是动态类型、动态绑定、动态加载?

    转载:https://www.cnblogs.com/dxb123456/p/5525343.html 动态: 主要是将数据类型的确定由编译时,推迟到了运行时. 这个问题其实浅涉及到两个概念,运行时和 ...

  3. RTTI (Run-Time Type Identification,通过运行时类型识别) 转

    参考一: RTTI(Run-Time Type Identification,通过运行时类型识别)程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型.   RTTI提供了以下两个 ...

  4. java运行时获得泛型类型

    引言 众所周知,java泛型最重要的特征是泛型擦除,所有泛型在编译时会转换成Object所以在java中运行时无法获得泛型的类型. 但是其实以上的规则是针对方法的内部变量的,如果是其他形式的泛型其实是 ...

  5. Java运行时环境---内存划分

    背景:听说Java运行时环境的内存划分是挺进BAT的必经之路. 内存划分: Java程序内存的划分是交由JVM执行的,而不像C语言那样需要程序员自己买单(C语言需要程序员为每一个new操作去配对del ...

  6. 【转】Java运行时数据区简介及堆与栈的区别

    理解JVM运行时的数据区是Java编程中的进阶部分.我们在开发中都遇到过一个很头疼的问题就是OutOfMemoryError(内存溢出错误),但是如果我们了解JVM的内部实现和其运行时的数据区的工作机 ...

  7. [Asp.net 5] Localization-Asp.net运行时多语言

    本节介绍的是Microsoft.AspNet.Localization工程.该工程是运行在Asp.net 5环境中的运行时多语言设置. ASP.net 5中间件技术 在新的Asp.net 5中,可以将 ...

  8. 《Effective C#》读书笔记-1.C# 语言习惯-2.使用运行时常量(readonly)而不是编译时常量(const)

    概念 编译时 编译时顾名思义就是正在编译的时候.那啥叫编译呢?就是编译器帮你把源代码翻译成机器能识别的代码.(当然只是一般意义上这么说,实际上可能只是翻译成某个中间状态的语言.比如Java只有JVM识 ...

  9. [二]Java虚拟机 jvm内存结构 运行时数据内存 class文件与jvm内存结构的映射 jvm数据类型 虚拟机栈 方法区 堆 含义

    前言简介 class文件是源代码经过编译后的一种平台中立的格式 里面包含了虚拟机运行所需要的所有信息,相当于 JVM的机器语言 JVM全称是Java Virtual Machine  ,既然是虚拟机, ...

随机推荐

  1. Redis基础知识小结

    Redis是一个高性能的key-value型数据库.Redis能读的速度是110000次/s,写的速度是81000次/s ,性能极高.Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全 ...

  2. Linux c codeblock的使用(三):使用函数库

    (一)概念 什么是函数库呢?一下子说概念大家可能不太熟悉,但是这实际上是大家在windows系统上经常见到的东西.没错,就是那些后缀为DLL的文件. linux上实际也有自己的函数库文件,文件类型为. ...

  3. 【java线程】锁机制

    转载于:https://blog.csdn.net/vking_wang/article/details/9952063 http://www.infoq.com/cn/articles/java-m ...

  4. spring中的AOP实验(二)

    软件151  王帅 1.目标对象的接口:IStudent.java  package  com.dragon.study;   public   interface  IStudent  {      ...

  5. mask_rcnn训练自己的数据集

    1.首先从官方下载mask_rcnn源码https://github.com/matterport/Mask_RCNN 2.首先将demo.ipynb转换成demo.py,这里我顺便更改为适用于我自己 ...

  6. git add.后回退 代码丢失

    记录一次操作git丢失代码的过程: 写完代码后:git staus git add. git status 发现有一堆.class 文件不想提交,想着代码回退到add 之前,使用了 git log 开 ...

  7. mybatis调用存储过程,获取返回的游标

    将调用存储过程参数放入map中,由于返回的游标中包含很多参数,所以再写一个resultmap与之对应,类型为hashmap.设置返回的jdbcType=CURSOR,resultMap设置为id对应的 ...

  8. 微信h5支付出现“商家参数格式有误,请联系商家解决”

    在浏览器进行微信h5支付时出现:

  9. vue 特点

    1.双向绑定  v-model 2.组件化  页面扩展 单文件组件 js css html 都在一个文件中 好处:前端组件化的突破性设计 scoped限制css的渲染,防止污染 lang 定义预处理器 ...

  10. datatable 添加列之前判断是否存在该列

    if (!dt.Columns.Contains("BDate")) { DataColumn dc1 = new DataColumn("BDate", ty ...