TypeToken 是google提供的一个解析Json数据的类库中一个类
Type listType = new TypeToken<LinkedList<User>>(){}.getType();
Type是java里的reflect包的Type ,TypeToken 是google提供的一个解析Json数据的类库中一个类
问题1:如果我没有写大括号{};就是TypeToken<LinkedList<User>>()后面的这个{},eclipse会报出 构造函数不可见,加上就好了,可是我在自己创建的2个测试类里
这样做就不行,如果构造是private的,加不加大括号都不行这是为什么
问题2:通常情况下,不加大括号是什么情况?加上又是什么情况,他们的含义是什么,作用是什么,
不加大括号表示很普通的new一个对象。。如果那个类的构造方法是私有的。。肯定不能直接new了。。就会编译报错。。
加上大括号表示你new了一个匿名内部类的对象。。比如new TypeToken<LinkedList<User>>(){}。。表示你new的是一个匿名内部类的对象。。这个匿名类继承自TypeToken类。。你可以在大括号里面像写其他普通类代码一样随意写代码。。你可以在里面定义个方法等等。。 主要你不能理解的原因我想是你不了解内部类。。多看内部类的知识就会明白了。。new TypeToken<LinkedList<User>>(){}匿名内部类常用在监听里面。。比如我们给一个按钮加监听。。比如
JButton btn = new JButton("test");
btn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { }
});
btn.addActionListener()方法接受的是一个ActionListener类型的对象。。而ActionListener是一个接口。。不能直接new。。所以本来我们应该写一个类实现ActionListener接口。。然后这里给他传一个那个实现类的对象。。但是。。我们不想那么麻烦了。。因为这种情况太多。。所以我们直接在这里创建了那个类。。之所以叫匿名。。就是我们没有给他取名字就让他叫ActionListener接口的名字。。然后在这里实现那个方法。。
最近在使用Google的Gson包进行Json和Java对象之间的转化,对于包含泛型的类的序列化和反序列化Gson也提供了很好的支持,感觉有点意思,就花时间研究了一下。
由于Java泛型的实现机制,使用了泛型的代码在运行期间相关的泛型参数的类型会被擦除,我们无法在运行期间获知泛型参数的具体类型(所有的泛型类型在运行时都是Object类型)。
但是有的时候,我们确实需要获知泛型参数的类型,比如将使用了泛型的Java代码序列化或者反序列化的时候,这个时候问题就变得比较棘手。

class Foo<T> {
T value;
}
Gson gson = new Gson();
Foo<Bar> foo = new Foo<Bar>();
gson.toJson(foo); // May not serialize foo.value correctly gson.fromJson(json, foo.getClass()); // Fails to deserialize foo.value as Bar

对于上面的类Foo<T>,由于在运行期间无法得知T的具体类型,对这个类的对象进行序列化和反序列化都不能正常进行。Gson通过借助TypeToken类来解决这个问题。

TestGeneric<String> t = new TestGeneric<String>();
t.setValue("Alo");
Type type = new TypeToken<TestGeneric<String>>(){}.getType(); String gStr = GsonUtils.gson.toJson(t,type);
System.out.println(gStr);
TestGeneric t1 = GsonUtils.gson.fromJson(gStr, type);
System.out.println(t1.getValue());

TypeToken的使用非常简单,如上面的代码,只要将需要获取类型的泛型类作为TypeToken的泛型参数构造一个匿名的子类,就可以通过getType()方法获取到我们使用的泛型类的泛型参数类型。
下面来简单分析一下原理。
要获取泛型参数的类型,一般的做法是在使用了泛型的类的构造函数中显示地传入泛型类的Class类型作为这个泛型类的私有属性,它保存了泛型类的类型信息。

public class Foo<T>{ public Class<T> kind; public Foo(Class<T> clazz){
this.kind = clazz;
} public T[] getInstance(){
return (T[])Array.newInstance(kind, 5);
} public static void main(String[] args){
Foo<String> foo = new Foo(String.class);
String[] strArray = foo.getInstance();
} }

这种方法虽然能解决问题,但是每次都要传入一个Class类参数,显得比较麻烦。Gson库里面对于这个问题采用了了另一种解决办法。
同样是为了获取Class的类型,可以通过另一种方式实现:

public abstract class Foo<T>{ Class<T> type; public Foo(){
this.type = (Class<T>) getClass();
} public static void main(String[] args) { Foo<String> foo = new Foo<String>(){};
Class mySuperClass = foo.getClass(); } }

声明一个抽象的父类Foo,匿名子类将泛型类作为Foo的泛型参数传入构造一个实例,再调用getClass方法获得这个子类的Class类型。
这里虽然通过另一种方式获得了匿名子类的Class类型,但是并没有直接将泛型参数T的Class类型传进来,那又是如何获得泛型参数的类型的呢, 这要依赖Java的Class字节码中存储的泛型参数信息。Java的泛型机制虽然在运行期间泛型类和非泛型类都相同,但是在编译java源代码成 class文件中还是保存了泛型相关的信息,这些信息被保存在class字节码常量池中,使用了泛型的代码处会生成一个signature签名字段,通过 签名signature字段指明这个常量池的地址。
关于class文件中存储泛型参数类型的具体的详细的知识可以参考这里:http://stackoverflow.com/questions/937933/where-are-generic-types-stored-in-java-class-files
JDK里面提供了方法去读取这些泛型信息的方法,再借助反射,就可以获得泛型参数的具体类型。同样是对于第一段代码中的foo对象,通过下面的代码可以得到foo<T>中的T的类型:
Type mySuperClass = foo.getClass().getGenericSuperclass();
Type type = ((ParameterizedType)mySuperClass).getActualTypeArguments()[0];
System.out.println(type);
运行结果是class java.lang.String。
分析一下这段代码,Class类的getGenericSuperClass()方法的注释是:
Returns the Type representing the direct superclass of the entity (class, interface, primitive type or void) represented by thisClass.
If the superclass is a parameterized type, the Type object returned must accurately reflect the actual type parameters used in the source code. The parameterized type representing the superclass is created if it had not been created before. See the declaration of ParameterizedType for the semantics of the creation process for parameterized types. If thisClass represents either theObject class, an interface, a primitive type, or void, then null is returned. If this object represents an array class then theClass object representing theObject class is returned
概括来说就是对于带有泛型的class,返回一个ParameterizedType对象,对于Object、接口和原始类型返回null,对于数 组class则是返回Object.class。ParameterizedType是表示带有泛型参数的类型的Java类型,JDK1.5引入了泛型之 后,Java中所有的Class都实现了Type接口,ParameterizedType则是继承了Type接口,所有包含泛型的Class类都会实现 这个接口。
实际运用中还要考虑比较多的情况,比如获得泛型参数的个数避免数组越界等,具体可以参看Gson中的TypeToken类及ParameterizedTypeImpl类的代码。
TypeToken 是google提供的一个解析Json数据的类库中一个类的更多相关文章
- Android中使用Gson解析JSON数据
Android中使用Gson解析JSON数据 在Android中可以使用Gson解析JSON数据 首先,从 code.google.com/p/google-gson/downloads/list ...
- Qt解析Json数据
1 JSON数据简介 JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式.它基于 ECMAScript (欧洲计算机协会制定的js规范) ...
- Java创建和解析Json数据方法——org.json包的使用(转)
org.json包的使用 1.简介 工具包org.json.jar,是一个轻量级的,JAVA下的json构造和解析工具包,它还包含JSON与XML, HTTP headers, Cookies, ...
- Android网络之数据解析----使用Google Gson解析Json数据
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- Java创建和解析Json数据方法(五)——Google Gson包的使用
(五)Google Gson包的使用 1.简介 Gson包中,使用最多的是Gson类的toJson()和fromJson()方法: ①toJson():将java对象转化为json数据 ...
- 服务端提供的JSON数据接口与用户端接收解析JSON数据
JSON格式的服务接口:http://www.cnblogs.com/visec479/articles/4118338.html 首先来了解下JSON格式解析 json结构的格式就是若干个 键/值( ...
- Google Gson解析Json数据应用实例
转自:http://lixigao449778967.blog.163.com/blog/static/24985164201269105928783/ 1.需要的Jar包 1) Google Gso ...
- Google中Gson的使用解析json数据-------学习篇
之前写过一篇Gson解析json数据的基本应用,这里不多说,直接上例子. 有兴趣的可以先阅读下之前那篇,这里附上链接: http://www.cnblogs.com/Ant-soldier/p/632 ...
- JS解析Json 数据并跳转到一个新页面,取消A 标签跳转
JS解析Json 数据并跳转到一个新页面,代码如下 $.getJSON("http://api.cn.abb.com/common/api/staff/employee/" + o ...
随机推荐
- 黄聪:VS2010中如何让webbrowser不弹出JS异常错误窗口(c#.net)
1.在属性窗口找到ScriptErrorsSuppressed,选择"true",这个选择的意思是,如果网页上有出现错误命令,这个错误提示将被抑制 2.[项目管理那里,在项目上右击 ...
- Python将数据写入excel或者txt,读入csv格式或xls文件,写入csv(写一行空一行解决办法)
1.写入excel,一开始不需要自己新建一个excel,会自动生成 attribute_proba是我写入的对象 import xlwt myexcel = xlwt.Workbook() sheet ...
- python + docker, 实现天气数据 从FTP获取以及持久化(三)-- python获取FTP数据
前言 经过前面两个小节的介绍,我们已经完成了MySQL数据库的搭建和数据库操作的事宜. 在本小节中,我们需要完成的任务是:使用python从FTP服务其上面获取文本文件. 搭建测试FTP服务器 LZ的 ...
- Clearsigned file isn't valid, got 'NOSPLIT' (does the network require authentication?)
ubuntu16在运行sudo apt-get update 命令后,报出错误: Clearsigned file isn't valid, got 'NOSPLIT' (does the netwo ...
- Android图片高斯模糊的一些方法
高斯模糊 高斯模糊就是将指定像素变换为其与周边像素加权平均后的值,权重就是高斯分布函数计算出来的值. 一种实现 点击打开链接<-这里是一片关于高斯模糊算法的介绍,我们需要首先根据高斯分布函数计算 ...
- Linux-vim编辑器与shell的简介
VIM编辑器 vi是Visual interface的简称,它可以执行输出.删除.查找.替换.块操作等众多文本操作. 用户可以根据自己的需要对vim进行定制,这是其他编辑程序所没有的. vim不是一 ...
- 给iOS开发新手送点福利,简述UIButton的属性和用法
UIButton属性 1.UIButton状态: UIControlStateNormal // 正常状态 UIControlStateHighlighted // 高 ...
- springcloud(六) Hystrix 熔断,限流
Hystrix 熔断: 首先仍然启动Eureka,这里就不说了. OrderController.java: package com.tuling.cloud.study.user.controlle ...
- Yii中使用RBAC完全指南
开始准备 Yii提供了强大的配置机制和很多现成的类库.在Yii中使用RBAC是很简单的,完全不需要再写RBAC代码.所以准备工作就是,打开编辑器,跟我来.设置参数.建立数据库 在配置数组中,增加以下内 ...
- Git--时光穿梭机之删除文件06
在Git中,删除也是一个修改操作,我们实际操作一下吧,先添加一个文件test.txt到Git并且提交 $ git add test.txt $ git commit -m "add test ...