在开发时,遇到了下面这条语句,不懂,然习之。

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可以解决这个问题,请看下面代码:

]);        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的同学有所帮助。

Java进阶(四)Java反射TypeToken解决泛型运行时类型擦除问题的更多相关文章

  1. Java 进阶巩固:什么是注解以及运行时注解的使用

    这篇文章 2016年12月13日星期二 就写完了,当时想着等写完另外一篇关于自定义注解的一起发.结果没想到这一等就是半年多 - -. 有时候的确是这样啊,总想着等条件更好了再干,等准备完全了再开始,结 ...

  2. GSON TypeToken 解决泛型问题

    Java进阶(四)Java反射TypeToken解决泛型运行时类型擦除的问题解决 在开发时,遇到了下面这条语句,不懂,然习之. private List<MyZhuiHaoDetailModel ...

  3. Java进阶之reflection(反射机制)——反射概念与基础

    反射机制是Java动态性之一,而说到动态性首先得了解动态语言.那么何为动态语言? 一.动态语言 动态语言,是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化.比如常见 ...

  4. Java进阶(四十三)线程与进程的区别

    Java进阶(四十三)线程与进程的区别 1.线程的基本概念   概念:线程是进程中执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必 ...

  5. Java进阶(四十七)Socket通信

    Java进阶(四十七)Socket通信   今天讲解一个 Hello Word 级别的 Java Socket 通信的例子.具体通讯过程如下: 先启动Server端,进入一个死循环以便一直监听某端口是 ...

  6. Java进阶(四十二)Java中多线程使用匿名内部类的方式进行创建3种方式

    Java中多线程使用匿名内部类的方式进行创建3种方式 package cn.edu.ujn.demo; // 匿名内部类的格式: public class ThreadDemo { public st ...

  7. Java进阶(四十)Java类、变量、方法修饰符讲解

    Java进阶(四十)Java类.变量.方法修饰符讲解 Java类修饰符 abstract: 将一个类声明为抽象类,没有实现的方法,需要子类提供方法实现. final: 将一个类生命为最终(即非继承类) ...

  8. Java泛型-内部原理: 类型擦除以及类型擦除带来的问题

    一:Java泛型的实现方法:类型擦除 大家都知道,Java的泛型是伪泛型,这是因为Java在编译期间,所有的泛型信息都会被擦掉,正确理解泛型概念的首要前提是理解类型擦除.Java的泛型基本上都是在编译 ...

  9. Java 反射(二)运行时获取类的信息

    目录 一.获得类的运行时结构 1. 获得类的名字 2. 获得类的属性 获取属性列表 获取指定属性 3. 获取类的方法 获得类的方法列表 获得指定方法 4. 获得的构造器 获得构造器列表 获得指定构造器 ...

随机推荐

  1. jdk1.7和jdk1.8区别

    转自:http://www.2cto.com/kf/201307/225968.html 本文是我学习了解了jdk7和jdk8的一些新特性的一些资料,有兴趣的大家可以浏览下下面的内容. 官方文档:ht ...

  2. web性能优化之--合理使用http缓存和localStorage做资源缓存

    一.前言 开始先扯点别的: 估计很多前端er的同学应该遇到过:在旧项目中添加新的功能模块.或者修改一些静态文件时候,当代码部署到线上之后,需求方验收OK,此时你送了一口气,当你准备开始得意于自己的ma ...

  3. PHP 5 Timezones

    PHP 支持的时区 下面是 PHP 支持的时区的完整列表,这些对一些 PHP 日期函数很有用. 非洲 美洲 南极洲 北冰洋 亚洲 大西洋 大洋洲 欧洲 印度洋 太平洋 非洲 Africa/Abidja ...

  4. Linux常见目录及命令介绍

    一.Linux中常用的目录介绍:     /        -根目录     /bin    -命令保存目录(普通用户亦可读取的命令)     /boot    -启动目录,启动相关文件     /d ...

  5. Rx系列二 | Observer | Observable

    Rx系列二 | Observer | Observable 上节课我们对RX的一些基本概念和使用JAVA代码实现了一个观察者,但是这只是对思路的一个讲解,在我们JAVA中,其实是已经封装好了观察者对象 ...

  6. ngx.re.match

    ngx.re.match syntax: captures, err = ngx.re.match(subject, regex, options?, ctx?, res_table?) contex ...

  7. python转lua最容易掉进去的坑--作用域

    你以为会依次打印2,4,8吗? 错. 2,2,2 value = 1 for i=1,3 do local value = value*2 print(value) end 你以为打印1吗?,错,输出 ...

  8. 带有进度条的WebView

    带有进度条的WebView 本篇继于WebView的使用 效果图 自定义一个带有进度条的WebView package com.kongqw.kbox.view; import android.con ...

  9. Objective-C与Java类的一些区别

    Objective-C与Java类的一些区别 OC类和C一样,需要有声明和定义,先上一段OC代码 #import <Foundation/Foundation.h> /* * 声明一个Pe ...

  10. ICL Auto Vectorization

    简介 此文简单介绍如何使用intel c++编译器实现向量化加速. 全文如下安排: base : 待优化的源代码. vectorization : 第一个向量化版本. aligned : 内存对其对向 ...