配套起来观看更好
json字符串 -> list对象
(1) 如果需要把json字符串 转成 集合这样复杂的类型, 需要使用gson提供的一个类
(2) TypeToken , 是一个自定义泛型类, 然后通过TypeToken来指定我们需要转换成的类型
com.google.gson.reflect import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class TypeToken<T> { final Class<? super T> rawType; final Type type; final int hashCode; protected TypeToken() { this.type = getSuperclassTypeParameter(this.getClass()); this.rawType = Types.getRawType(this.type); this.hashCode = this.type.hashCode(); }
分析一
(1) 返回类型的完整路径java.util.List<com.wyxdu.json.Book>
(2) gson的设计者,需要得到类型的完整路径,然后进行底层反射
(3) 所以gson 设计者就提供TypeToken, 来搞定.
分析二
(1) 如果我们 new TypeToken<List>() 提示’TypeToken()’ has protected access in ‘com.google.gson.reflect.TypeToken’
(2) 因为TypeToken 的无参构造器是protected , 而 new TypeToken<List>() 就是调用其无参构造器
(3) 根据java基础, 如果一个方法是protected ,而且不在同一个包, 是不能直接访问的, 因此报错
(4) 为什么 new TypeToken<List>(){} 使用就可以,这里就涉及到匿名内部类的知识.
(5) 当 new TypeToken<List>(){} 其实这个类型就是不是 TypeToken 而是一个匿名内部类(子类)
(6) 而且这个匿名内部类是有自己的无参构造器(隐式), 根据java基础规则 当执行子类的无参构造器时, 默认super();
模拟实现
首先
建立一个包然后创建一个类 我这里就是Text/T1.java
package t1; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class A<T> { protected A() { System.out.println("A的protected A()被调用..."); } }
其次
再建立一个包然后创建一个类 我这里就是Text2/T2.java
package t2; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import t1.A; public class Test { public static void main(String[] args) { //'A()' has protected access in 'com.t1.A' A a = new A<String>(){}; System.out.println(a.getClass());//Test$1 } }
如果直接调用会报错 ‘A()’ has protected access in ‘t1.A’
- 因为A类和Test类不在同一个包
- 就不能访问A类的protected 方法,包括构造器
- A(){} 就是一个匿名内部类, 可以理解成是A类子类
- A(){} 匿名内部类,有一个隐式的无参构造器,根据java基础 无参构造器 有默认super()
- 当你执行 new A(){} 会调用到A类的无参的protected 构造器
总结
当我们需要调用其他包下的受保护的方法时我们应该采用匿名内部类的方式去调用 相当于是创建了一个A类的子类