001_gson的泛型封裝
阿新 • • 發佈:2018-11-07
我估計很多使用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