您现在的位置是:网站首页> 内容页

如何在运行时(Runtime)获得泛型的真正类型

  • 蒙特卡罗网址导航
  • 2019-07-12
  • 421人已阅读
简介前言由于Java的类型擦除机制,在编译时泛型都被转为了Object,例如List<String>经过编译之后将变为类型List。可以通过以下的方式再运行时获得泛型的真正类型

前言

由于Java 的类型擦除机制,在编译时泛型都被转为了Object,例如List<String>经过编译之后将变为类型 List。可以通过以下的方式再运行时获得泛型的真正类型

泛型如何获得具体类型

List 例子如下

来自:https://stackoverflow.com/questions/1942644/get-generic-type-of-java-util-list

package testimport java.lang.reflect.Fieldimport java.lang.reflect.ParameterizedTypeimport java.util.ArrayListimport java.util.Listpublic 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.typeimport java.lang.reflect.ParameterizedTypeimport java.lang.reflect.Typepublic 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

1 0 9)

文章评论

Top