首页 > 代码库 > gson的 TypeToken

gson的 TypeToken

 

需要解析json,看了gson的文档,发现有Type type= new TypeToken<List<User>>(){}.getType();来获取需要序列化的对象的类信息,这里主要记录两个知识点

一、匿名内部类

什么情况下需要使用匿名内部类?如果满足下面的一些条件,使用匿名内部类是比较合适的:
      a·只用到类的一个实例。
      b·类在定义后马上用到(一般只用一次)。
      c·类非常小(SUN推荐是在4行代码以下)
      d·给类命名并不会导致你的代码更容易被理解。
在使用匿名内部类时,要记住以下几个原则:
      a·匿名内部类不能有构造方法。
      b·匿名内部类不能定义任何静态成员、方法和类。
      c·匿名内部类不能是public,protected,private,static。
      d·只能创建匿名内部类的一个实例。
      e·一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
      f·因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。
结合本例子:

将需要获取类型的泛型类作为TypeToken的泛型参数构造一个匿名的子类,就可以通过getType()方法获取到我们使用的泛型类的泛型参数类型。不加大括号表示很普通的new一个对象。如果那个类的构造方法是私有的,直接new会编译报错。(这里的构造方法是protect,也无法直接new,是gson获取泛型信息进行内部处理的选择放手)
加上大括号表示你new了一个匿名(内部)类的对象。比如new TypeToken<LinkedList<User>>(){}。表示你new的是一个匿名内部类的对象。这个匿名类继承自TypeToken类。你可以在大括号里面像写其他普通类代码一样随意写代码。
就相当于在方法代码中,直接定义并new 了一个TypeToken的匿名子类。

二、泛型擦除的基础理解

技术分享

上面的代码我们声明了两个泛型的ArrayList类型,一个泛型的类型参数是String,另外一个是Integer;然后我们输出了两个泛型的Class,并输出两个list的类型是否是同一个list。我们看下输出的结果:

技术分享

前两个输出都是java.util.ArrayList,而第三个输出竟然是true,也就是认为stringListintList的类型是一样的。这就是所谓的泛型类型擦除。运行时我们不知道泛型类型的类型参数是什么了。

TypeToken可以解决这个问题,请看下面代码:

技术分享

注意上面第一行代码使用了一个空的匿名类。第二行使用了resolveType方法解析出泛型类型,第三行代码打印出泛型类型,输出是:

技术分享

可以看出TypeToken解析出了泛型参数的具体类型。

 

gson的 TypeToken