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可以解决这个问题,请看下面代码:
]); 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解决泛型运行时类型擦除问题的更多相关文章
- Java 进阶巩固:什么是注解以及运行时注解的使用
这篇文章 2016年12月13日星期二 就写完了,当时想着等写完另外一篇关于自定义注解的一起发.结果没想到这一等就是半年多 - -. 有时候的确是这样啊,总想着等条件更好了再干,等准备完全了再开始,结 ...
- GSON TypeToken 解决泛型问题
Java进阶(四)Java反射TypeToken解决泛型运行时类型擦除的问题解决 在开发时,遇到了下面这条语句,不懂,然习之. private List<MyZhuiHaoDetailModel ...
- Java进阶之reflection(反射机制)——反射概念与基础
反射机制是Java动态性之一,而说到动态性首先得了解动态语言.那么何为动态语言? 一.动态语言 动态语言,是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化.比如常见 ...
- Java进阶(四十三)线程与进程的区别
Java进阶(四十三)线程与进程的区别 1.线程的基本概念 概念:线程是进程中执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必 ...
- Java进阶(四十七)Socket通信
Java进阶(四十七)Socket通信 今天讲解一个 Hello Word 级别的 Java Socket 通信的例子.具体通讯过程如下: 先启动Server端,进入一个死循环以便一直监听某端口是 ...
- Java进阶(四十二)Java中多线程使用匿名内部类的方式进行创建3种方式
Java中多线程使用匿名内部类的方式进行创建3种方式 package cn.edu.ujn.demo; // 匿名内部类的格式: public class ThreadDemo { public st ...
- Java进阶(四十)Java类、变量、方法修饰符讲解
Java进阶(四十)Java类.变量.方法修饰符讲解 Java类修饰符 abstract: 将一个类声明为抽象类,没有实现的方法,需要子类提供方法实现. final: 将一个类生命为最终(即非继承类) ...
- Java泛型-内部原理: 类型擦除以及类型擦除带来的问题
一:Java泛型的实现方法:类型擦除 大家都知道,Java的泛型是伪泛型,这是因为Java在编译期间,所有的泛型信息都会被擦掉,正确理解泛型概念的首要前提是理解类型擦除.Java的泛型基本上都是在编译 ...
- Java 反射(二)运行时获取类的信息
目录 一.获得类的运行时结构 1. 获得类的名字 2. 获得类的属性 获取属性列表 获取指定属性 3. 获取类的方法 获得类的方法列表 获得指定方法 4. 获得的构造器 获得构造器列表 获得指定构造器 ...
随机推荐
- JSON.parse()在火狐中的BUG
//用sessionStorage解决load页面刷新问题 { //sessionStorage.removeItem("loadInfo"); var loadInfo=de ...
- RabbitMQ用户管理
rabbitmq常用命令 add_user <UserName> <Password> delete_user <UserName> chan ...
- Memcached在Linux环境下的使用详解
一.引言 写有关NoSQL数据库有关的文章已经有一段时间了,可以高兴的说,Redis暂时就算写完了,从安装到数据类型,在到集群,几乎都写到了.如果以后有了心得,再补充吧.然后就 ...
- c#下winform的ftp上传
/* FTPFactory.cs Better view with tab space=4 Written by Jaimon Mathew (jaimonmathew@rediffmail.com) ...
- vue+node.js+webpack开发微信公众号功能填坑——组件按需引入
初次开发微信公众号,整体框架是经理搭建,小喽喽只是实现部分功能,整体页面效果 整个页面使用两个组件:布局 FlexBox,搜索框 Search,demo文档 http://vue.ydui.org/d ...
- JavaScript 对象JavaScript 对象
JavaScript 中的所有事物都是对象:字符串.数值.数组.函数... 此外,JavaScript 允许自定义对象. 所有事物都是对象 JavaScript 提供多个内建对象,比如 String. ...
- Python3 XML解析
什么是XML? XML 指可扩展标记语言(eXtensible Markup Language),标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言. 你可以通过本站学习XML教程 ...
- eclipse安装和中文汉化,以及配置
官网下载 eclipse http://www.eclipse.org/downloads/eclipse-packages/ ----选择 "Eclipse IDE for Java De ...
- Swift中方法(method)所谓的lazy绑定简介
我们知道在ruby之类的动态语言中对象方法可以先从类中预先抽取,然后再应用到某个具体对象上.这称为无绑定的method对象,也可以叫做lazy绑定. 下面举个例子: irb(main):004:0&g ...
- 【完整的App项目】颖火虫笔记
这是本人花大概一个星期开发出来的一款App,这是一款类似印象笔记的App,随时记录您的生活点滴.首先说一下自己为何要开发这款App,因为自己手机系统自带的笔记应用功能太low,界面不够漂亮,所以自己就 ...