直男码农傲娇求赞求评论~^_^~
假设有个User类,我们想用Gson将一个字符串解析成User类,那么可以像下面这样,比较简单:
Gson gson = new Gson();
User user = gson.fromJson("user对象json字符串",User.class)
但是如果是一个User数组的字符串呢,我们希望解析成List<User> 类型的一个数组
这个List<User>不能直接.class,我们可以用下面这个方法
public <T> T fromJson(String json, Type typeOfT){
}
然后这里的 Type typeOfT,即List<User> 的Type 如何获取呢?
可以这样:(利用Gson库中的TypeToken类)就可以获取到List<User> 的Type,进而完成解析
Type type = new TypeToken<List<User>>(){}.getType();
那么TypeToken内部究竟是如何做的呢?下面请看源码
public class TypeToken<T> {
final Class<? super T> rawType;
final Type type;
final int hashCode;
/**
* Gets underlying {@code Type} instance.
*/
public final Type getType() {
return type;
}
//protected 修饰符不能在外部直接new对象
/**
* Constructs a new type literal. Derives represented class from type
* parameter.
*
* <p>Clients create an empty anonymous subclass. Doing so embeds the type
* parameter in the anonymous class's type hierarchy so we can reconstitute it
* at runtime despite erasure.
*/
@SuppressWarnings("unchecked")
protected TypeToken() {
this.type = getSuperclassTypeParameter(getClass());
this.rawType = (Class<? super T>) $Gson$Types.getRawType(type);
this.hashCode = type.hashCode();
}
//默认修饰符 不能在外部直接new对象
/**
* Unsafe. Constructs a type literal manually.
*/
@SuppressWarnings("unchecked")
TypeToken(Type type) {
this.type = $Gson$Types.canonicalize($Gson$Preconditions.checkNotNull(type));
this.rawType = (Class<? super T>) $Gson$Types.getRawType(this.type);
this.hashCode = this.type.hashCode();
}
/**
* Returns the type from super class's type parameter in {@link $Gson$Types#canonicalize
* canonical form}.
*/
static Type getSuperclassTypeParameter(Class<?> subclass) {
//注意注意,这句话比较重要,这个是获取父类的带泛型的Class对象
//因为构造方法已经不能直接用于在外部直接new对象,所以在外部只能通过子类的方式来构造对象
//而匿名内部类就是一个对该类的继承方式
//通过匿名内部类的方式得到一个对象,通过该对象getClass.getGenericSuperclass()方法
//获取到父类的带泛型的Class对象,就是TypeToken 本身了
Type superclass = subclass.getGenericSuperclass();
if (superclass instanceof Class) {
throw new RuntimeException("Missing type parameter.");
}
//因为TypeToken上定义了泛型,在外部使用时传了具体的类型,
//获取的genericSuperclass就是ParameterizedType
//进而通过ParameterizedType的getActualTypeArguments方法获取实际的泛型数组
//因为TypeToken类上只定义了一个泛型参数,所以这里获取的Type[]大小就是1了
//直接[0],就获取到了传入的实际类型Type,即传入的List<User>
ParameterizedType parameterized = (ParameterizedType) superclass;
//canonicalize 看字面是规范化的意思,内部主要是Gson将Java jdk中Type的各个实现类转换成了Gson自
//己对Type的各个实现类 (测试发现不调用这个方法也能对数组类型的字符串也能解析成功)
return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
}
//省略代码。。。。
}
关于Type 和 ParameterizedType
Type 有 5个子类/接口,其中一个就是 ParameterizedType
而 ParameterizedType 里有三个方法
直接举例,如果是List<User> 那么Type[] 就是[User],
如果是Map<Integer,String>,那么Type[] 就是[Integer,String]
如果是HashMap<Integer,List<User>>,那么Type[]就是[Integer,List<User>]
总之,就是获取最外层<>里面的内容
Type[] getActualTypeArguments();
举例:如果是List<User> 那么Type 就是List,
如果是Map<Integer,String>,那么Type 就是Map
如果是HashMap<Integer,List<User>>,那么Type[]就是HashMap
Type getRawType();
Type getOwnerType();
关于Type更多内容可以参考
https://www.jianshu.com/p/e8eeff12c306