Gson中TypeToken如何实现获取参数类型

情景引入:
在使用GSON解析一段JSON数组时,需要借助TypeToken将期望解析成的数据类型传入到fromJson()方法中,如下:

List<Person> people = gson.fromJson(jsonData, new TypeToken<List<Person>>(){}.getType());
   
   
  • 1
                                                             ————出自《第一行代码》

   
   
  • 1
  • 2

假设一段JSON格式的数据如下:

   [{"name":"Tom","age":"10"},
    {"name":"Lucy","age":"11"},
    {"name":"Lily","age":"11"}]
   
   
  • 1
  • 2
  • 3

那木,new TypeToken<List<Person>>(){}.getType()是怎么获取到泛型参数类型的呢?

解析:

首先,new TypeToken<List<Person>>(){}是一个匿名内部类,其等价MyTypeToken<List<Person>> extends TypeToken(){},但是{}里是空的,既然什么都没有改变,为什么还要这么用呢?下面看源码

进一步,TypeToken源码如下:

public class TypeToken<T> {
    final Class<? super T> rawType;
    final Type type;
    final int hashCode;

//这里的空参构造方法权限修饰符是protected,那木只有其子类可访问,预示着要使用子类构造。
    protected TypeToken() {
        this.type = getSuperclassTypeParameter(this.getClass());//这里传入的子类,后面2行不用看
        this.rawType = Types.getRawType(this.type);
        this.hashCode = this.type.hashCode();
    }

   ...

    static Type getSuperclassTypeParameter(Class<?> subclass) {
        Type superclass = subclass.getGenericSuperclass();//获取到子类的父类Type
        if(superclass instanceof Class) {
            throw new RuntimeException("Missing type parameter.");
        } else {
            ParameterizedType parameterized = (ParameterizedType)superclass;//将Type类型向下转型为参数化类型ParameterizedType
            return Types.canonicalize(parameterized.getActualTypeArguments()[0]);//这里getActualTypeArguments()返回的是一个数组,由于只有一个泛型参数,直接[0]。
        }
    }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

若是还不是太明白,那就是Java这块的东西还不熟。上面的原码部分牵涉到Java的知识点:

Type:

其是一个接口java.lang.reflect.Type,主要有5类:
raw types:一般类型,例如:String,Collections ,Math,Number…
parameterized types : 参数化类型,例如:List<String>集合中常用…
array types : 数组类型
type variables :类型变量,不确定其类型,例如List<? extends Person>
primitive types : 基本类型,int,float…

详细参见:http://blog.csdn.net/kaka123ac/article/details/4470813

getSuperClass() 与 getGenericSuperclass()区别:

前者,返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class(由于编译擦除,没有显示泛型参数:在运行期间,泛型参数类型一律为Object类型)。
后者,返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的直接超类的 Type(包含泛型参数)。

详细参见: http://www.cnblogs.com/maokun/p/6773203.html


GSON源码中Types.canonicalize方法,将Java 中的Type实现,转化为自己内部的数据实现,想要继续探讨,可以去看源码或者参见:https://my.oschina.net/u/874727/blog/750473


最后,我们来实践一下,实现Java中如何获取参数类型,TypeToken内部就是Java实现,然后转换。直接上代码:

public class TypeToken1<String> {

    public TypeToken1() {
    }
    //为了测试,这个类什么都不干,手动去获取参数类型String
}

----------

public class TypeTokenTest {
    public static void main(String[] args){

        Type mySuperClass = new TypeToken1<String>(){}.getClass().getGenericSuperclass();
        Type type = ((ParameterizedType) mySuperClass).getActualTypeArguments()[0];
        System.out.println("获得的泛型参数:"+type);

    }
}

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

运行结果:

获得的泛型参数:class java.lang.String

Process finished with exit code 0

                                            <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/production/markdown_views-ea0013b516.css">
                                </div>
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值