Java进阶(四)Java反射TypeToken解决泛型运行时类型擦除的问题解决

在开发时,遇到了下面这条语句,不懂,然习之。
private List<MyZhuiHaoDetailModel> listLottery = new ArrayList<MyZhuiHaoDetailModel>();

Gson gson=new Gson();

JSONObject object=new JSONObject(callbackValue);

listLottery =  gson.fromJson(object.getString("lists"),

new TypeToken<List<MyZhuiHaoDetailModel>>() {

}.getType());

GSON提供了 TypeToken 这个类来帮助我们捕获(capture)像List<MyZhuiHaoDetailModel>这样的泛型信息。上文创建了一个匿名内部类,这样,Java编译器就会把泛型信息编译到这个匿名内部类里,然后在运行时就可以被 getType()方法用反射API提取到。 下面来看看gson的反序列化,Gson提供了fromJson()方法来实现从Json相关对象到java实体的方法。 在日常应用中,我们一般都会碰到两种情况,转成单一实体对象和转换成对象列表或者其他结构。 先来看第一种: 比如json字符串为:{"name":"name0","age":0} 代码: Person person = gson.fromJson(str, Person.class);提供两个参数,分别是json字符串以及需要转换对象的类型。 第二种,转换成列表类型: 代码:

List<Person> ps = gson.fromJson(str, new TypeToken<List<Person>>(){}.getType());

for(int i = 0; i < ps.size() ; i++)

{

     Person p = ps.get(i);

     System.out.println(p.toString());

}

可以看到上面的代码使用了TypeToken,它是gson提供的数据类型转换器,可以支持各种数据集合类型转换。 经过比较,gson和其他现有java json类库最大的不同是gson需要序列化的实体类不需要使用annotation来标识需要序列化得字段,同时gson又可以通过使用annotation来灵活配置需要序列化的字段。 另外,java反射包中的TypeToken类是用来解决java运行时泛型类型被擦除的问题的,有点不好理解,我们通过一个例子来认识什么是泛型的运行时类型擦除。

 ArrayList<String> stringList = Lists.newArrayList();  

       ArrayList<Integer> intList = Lists.newArrayList();        

       System.out.println("intList type is " + intList.getClass());    

      System.out.println("stringList type is " + stringList.getClass());  

      System.out.println(stringList.getClass().isAssignableFrom(intList.getClass()));

上面的代码我们声明了两个泛型的ArrayList类型,一个泛型的类型参数是String,另外一个是Integer;然后我们输出了两个泛型的Class,并输出两个list的类型是否是同一个list。我们看下输出的结果:intList type is class java.util.ArrayListstringList type is class java.util.ArrayListtrue前两个输出都是java.util.ArrayList,而第三个输出竟然是true,也就是认为stringList和intList的类型是一样的。这就是所谓的泛型类型擦除。运行时我们不知道泛型类型的类型参数是什么了。TypeToken可以解决这个问题,请看下面代码: TypeToken<ArrayList<String>> typeToken = new TypeToken<ArrayList<String>>() {}; TypeToken<?> genericTypeToken = typeToken.resolveType(ArrayList.class.getTypeParameters()[0]); System.out.println(genericTypeToken.getType());注意上面第一行代码使用了一个空的匿名类。第二行使用了resolveType方法解析出泛型类型,第三行代码打印出泛型类型,输出是:class java.lang.String可以看出TypeToken解析出了泛型参数的具体类型。TypeToken的方法列表如下:方法 描述getType() 获得包装的java.lang.reflect.Type.getRawType() 返回大家熟知的运行时类getSubtype(Class<?>) 返回那些有特定原始类的子类型。举个例子,如果这有一个Iterable并且参数是List.class,那么返回将是List。getSupertype(Class<?>) 产生这个类型的超类,这个超类是指定的原始类型。举个例子,如果这是一个Set并且参数是Iterable.class,结果将会是Iterable。isAssignableFrom(type) 如果这个类型是 assignable from 指定的类型,并且考虑泛型参数,返回true。List<? extends Number>是assignable from List,但List没有.getTypes() 返回一个Set,包含了这个所有接口,子类和类是这个类型的类。返回的Set同样提供了classes()和interfaces()方法允许你只浏览超类和接口类。isArray() 检查某个类型是不是数组,甚至是<? extends A[]>。getComponentType() 返回组件类型数组。 Gson的基本使用就是这么多,至于annotation方面可以参考gson的官方文档,希望能对初学java和gson的同学有所帮助。

GSON TypeToken 解决泛型问题的更多相关文章

  1. Java进阶(四)Java反射TypeToken解决泛型运行时类型擦除问题

    在开发时,遇到了下面这条语句,不懂,然习之. private List<MyZhuiHaoDetailModel> listLottery = new ArrayList<MyZhu ...

  2. Gson通过借助TypeToken获取泛型参数的类型的方法

    最近在使用Google的Gson包进行Json和Java对象之间的转化,对于包含泛型的类的序列化和反序列化Gson也提供了很好的支持,感觉有点意思,就花时间研究了一下. 由于Java泛型的实现机制,使 ...

  3. Gson通过借助TypeToken获取泛型参数的类型的方法(转)

    最近在使用Google的Gson包进行Json和Java对象之间的转化,对于包含泛型的类的序列化和反序列化Gson也提供了很好的支持,感觉有点意思,就花时间研究了一下. 由于Java泛型的实现机制,使 ...

  4. 代码混淆 GSON完满解决

    头疼的问题,json使用了google的gson三方包,可是混淆的时候出了问题 明明已经按照gson的官方文档,把混淆脚本加上去了,却还是出问题. 今天同事找到一篇博客,关于这个问题的: 我们是将js ...

  5. 使用Gson轻松解决复杂结构的Json数据解析

    转载请注明来源: http://blog.csdn.net/kjunchen/article/details/50961803 JSON简介 JSON(JavaScript Object Notati ...

  6. [转]用GSON 五招之内搞定任何JSON数组

    关于GSON的入门级使用,这里就不提了,如有需要可以看这篇博文 <Google Gson的使用方法,实现Json结构的相互转换> ,写的很好,通俗易懂. 我为什么写这篇文章呢?因为前几晚跟 ...

  7. Gson基本操作,JsonObject,JsonArray,String,JavaBean,List互转

    (转自)https://www.cnblogs.com/robbinluobo/p/7217387.html String.JsonObject.JavaBean 互相转换 User user = n ...

  8. [转] Android:用GSON 五招之内搞定任何JSON数组

    [From] http://www.open-open.com/lib/view/open1472632967912.html 写在前面 关于GSON的入门级使用,这里就不提了,如有需要可以看这篇博文 ...

  9. 使用GSON和泛型解析约定格式的JSON串(转)

    时间紧张,先记一笔,后续优化与完善. 解决的问题: 使用GSON和泛型解析约定格式的JSON串. 背景介绍: 1.使用GSON来进行JSON串与java代码的互相转换. 2.JSON的格式如下三种: ...

随机推荐

  1. [BZOJ]1018 堵塞的交通(SHOI2008)

    一道有点神的线段树. Description 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可以被看成是一个2行C列的矩形网格,网格上的每个点代表一个城 ...

  2. 抽象方法不能是static或native或synchroniz

    abstract 是抽象了,只有声明,没有具体的实现方法 static是静态的,是一种属于类而不属于对象的方法或者属性,而我们知道,类其实也是一个对象,他是在class文件加载到虚拟机以后就会产生的对 ...

  3. 勤拂拭软件 java web 开发教程(1) - 开发环境搭建

    勤拂拭软件系列教程 之 Java Web开发之旅(1) Java Web开发环境搭建 1 前言 工作过程中,遇到不少朋友想要学习jsp开发,然而第一步都迈不出,连一个基本的环境都没有,试问,如何能够继 ...

  4. PHP Laravel框架入门心得 | How to study PHP Laravel Framework

    PHP有不少开发框架,其中比较出名的有Symfony和Laravel. 我说说我最近入门Laravel的感受和学习方法吧. 1.第一个感受是Laravel的社区讨论和学习资源真的是太棒了,中文化也做得 ...

  5. Python中dict的功能介绍

    Dict的功能介绍 1. 字典的两种函数(方法) 1. 字典的内置函数 包含关系 格式:x.__contains__(key)等同于key in x 例如:dic = {'ab':23,'cd':34 ...

  6. 5-15 QQ帐户的申请与登陆 (25分) HASH

    实现QQ新帐户申请和老帐户登陆的简化版功能.最大挑战是:据说现在的QQ号码已经有10位数了. 输入格式: 输入首先给出一个正整数NN(\le 10^5≤10​5​​),随后给出NN行指令.每行指令的格 ...

  7. c语言第六次作业v

    (一)改错题 序列求和:输入一个正实数eps,计算序列部分和 1 - 1/4 + 1/7 - 1/10 + ... ,精确到最后一项的绝对值小于eps(保留6位小数). 输入输出样例: Input e ...

  8. js error

    0x800a0259 - JavaScript 运行时错误: 未知的运行时错误 <p id="navigatorInfo"></p> var txt = & ...

  9. 打印n阶菱形

    #打印n阶菱形 def print_rhombus(n): #打印正三角 for i in range(1,n+1): x_num = 2*i-1 #每一层的*数量 space_num = n - i ...

  10. Docker 自定义网桥

    除了默认的 docker0 网桥,用户也可以指定网桥来连接各个容器. 在启动 Docker 服务的时候,使用 -b BRIDGE或--bridge=BRIDGE 来指定使用的网桥. 如果服务已经运行, ...