版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33781658/article/details/81516591
我估计很多使用gson的人都会遇到这个问题
先来说说我怎么发现这个问题的吧
我们知道gson最简单的一个用法
就是把字符串转换成object或者list
举个例子:
public class User {
private String name;
private String age;
}
String string = "{\"name\":\"abc\",\n" + "\"age\":\"18\"}";
Gson gson = new Gson();
User user = gson.fromJson(string, new TypeToken<User>(){}.getType());
这段代码是没问题的
解析出来后可以拿到user没问题
我们发现如果要解析的话
每次都要写
new TypeToken<User>(){}.getType()
就很麻烦
那么聪明的猴急的我们肯定就想要把他封装一下了
我们做一点小修改,做一点简单的小封装
String string = "{\"name\":\"abc\",\n" + "\"age\":\"18\"}";
Gson gson = new Gson();
Type type = getType(User.class);
User user = gson.fromJson(string, type);
public <T> Type getType(Class<T> clazz) {
return new TypeToken<T>() {
}.getType();
}
这时候我们发现,居然报错了
com.google.gson.internal.LinkedTreeMap cannot be cast to com.User
我当时就懵逼了
我不就抽了个方法吗
怎么这样都不行
这其实和java的泛型擦除机制有关系
简单来说,JVM在编译的时候,是不看泛型的
所以在创建Type的时候根本不知道你这个T泛型到底是什么
具体可以百度一下 泛型擦除
因为我也不太懂
现在我们应该怎么解决这个问题呢
说实话当时我都想放弃了
大不了每次都写
new TypeToken<User>(){}.getType()
算了
但是,我们还是努力尝试一下,才会有进步
现在网上最常用的方法就是这样做
我知道很多人看到的时候会很懵逼
因为有一种 知其然而不知其所以然 的感觉
我也是非常懵逼
但是我也确实不知道这个原理
所以我们暂时只能照做了
不过这个方法还是非常简单的
没有多少代码
所以我们可以先解决这个问题
等以后自己的技术实力提升了再去研究原理
先创建一个类
public class ParameterizedTypeImpl implements ParameterizedType {
private final Class raw;
private final Type[] args;
public ParameterizedTypeImpl(Class raw, Type[] args) {
this.raw = raw;
this.args = args != null ? args : new Type[0];
}
@Override
public Type[] getActualTypeArguments() {
return args;
}
@Override
public Type getRawType() {
return raw;
}
@Override
public Type getOwnerType() {
return null;
}
}
然后我们把我们刚刚解析的代码也做一点修改
public static <T> User fromJsonObject(String reader, Class<T> clazz) {
Type type = new ParameterizedTypeImpl(User.class, new Class[]{clazz});
return new Gson().fromJson(reader, type);
}
String string = "{\"name\":\"abc\",\n" + "\"age\":\"18\"}";
User user = fromJsonObject(string, User.class);
现在我们成功解析出了user