Gson解析中的Typetoken获取数据类型

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

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

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

   [{"name":"Tom","age":"10"},
    {"name":"Lucy","age":"11"},
    {"name":"Lily","age":"11"}]

那么,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 {            //将Type类型向下转型为参数化类型ParameterizedType
            ParameterizedType parameterized = (ParameterizedType)superclass;
            //这里getActualTypeArguments()返回的是一个数组,由于只有一个泛型参数,直接[0]。
            return Types.canonicalize(parameterized.getActualTypeArguments()[0]);
        }
    }

若是还不是太明白,那就是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);

    }
}

运行结果:

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

Process finished with exit code 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值