前言
由于 Java 的类型擦除机制, 在编译时泛型都被转为了 Object, 例如 List<String > 经过编译之后将变为类型 List. 可以通过以下的方式再运行时获得泛型的真正类型
泛型如何获得具体类型
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 的例子如下
- 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);
- }
来源: https://www.cnblogs.com/xiaoheike/p/9867060.html