问题
在Gson中可以使用TypeToken来支持List< >的泛型解析。
Type type = new TypeToken<List<xxx>>(){}.getType();
T result = new Gson().fromJson(str, type);
为了在api接口中限制返回的解析结果,并且为了简化代码只希望在方法参数上指定一次具体解析类,尝试对Gson解析过程进行以下封装。
Type type = new TypeToken<T>(){}.getType();
T result = new Gson().fromJson(str, type);
发现result被解析为com.google.gson.internal.LinkedTreeMap, 而不是使用时指定的List< >,分析后发现是java中的类型擦除导致的。
类型擦除
在编译期间检测到泛型的具体使用,并自动生成对应的具体实现。 因此只能在具体调用时去指定类型。
- 将所有的泛型参数用其最左边界(最顶级的父类型)类型替换。
- 移除所有的类型参数。
相关介绍 blog.csdn.net/gstormspire…
- 不能用同一泛型类的实例区分方法签名
- 泛型类的静态变量是共享的
解决方案
//stringCallback指定了调用时的具体泛型,如:CallBack<List<Data>>最终返回的Type是List<Data>
static Type getType(@NonNull ApiCallBack stringCallback){
//返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的直接超类的 Type。
Type genericSuperclass = stringCallback.getClass().getGenericSuperclass();
ParameterizedType types = (ParameterizedType) genericSuperclass;
if(types == null){
throw new IllegalStateException("泛型获取异常");
}
Type typeArgument;
try{
Type[] actualTypeArguments = types.getActualTypeArguments();
typeArgument = actualTypeArguments[0];
//返回表示此类型实际类型参数的 Type 对象的数组(),想要获取第一个泛型的Class,所以索引写0
}catch (Exception e){
throw new IllegalStateException("泛型获取异常");
}
return typeArgument;
}