在SharedPreferencesde的拓展使用:存储List的用法中,大家基本都能搜到下面这段代码:
public <T> List<T> getDataList(String tag) {
List<T> datalist = new ArrayList<T>();
String strJson = preferences.getString(tag, null);
if (null == strJson) {
return datalist;
}
Gson gson = new Gson();
datalist = gson.fromJson(strJson, new TypeToken<List<T>>() {}.getType());
return datalist;
}
但其实这段代码的使用是有问题的,我在使用这段代码获取保存的list时,提示Json解析错误,简单看了下,问题发生在下面这句代码:
datalist = gson.fromJson(strJson, new TypeToken<List<T>>() {}.getType());
这句在实际执行的时候,List<T>中的T并未传入实际的泛型参数,导致Gson按照LinkedTreeMap来解析JSON,以致发生了错误;
这就是一个在编译期泛型类型擦除所导致的问题;
相关泛型擦除的资料可参考:
Gson TypeToken with dynamic ArrayList item type
Java泛型-类型擦除
下面提供解决方案:
1.更改解析方式(推荐)
public <T> List<T> getDataList(String tag, Class<T> cls) {
List<T> datalist = new ArrayList<T>();
String strJson = preferences.getString(tag, null);
if (null == strJson) {
return datalist;
}
JsonArray array = new JsonParser().parse(strJson).getAsJsonArray();
for(final JsonElement elem : array){
datalist.add(new Gson().fromJson(elem, cls));
}
return datalist;
}
2.增加一步对type的处理
public <T> List<T> getDataList(String tag, Class<T> cls) {
List<T> datalist = new ArrayList<T>();
String strJson = preferences.getString(tag, null);
if (null == strJson) {
return datalist;
}
Gson gson = new Gson();
Type type = new ListParameterizedType(cls);
datalist = gson.fromJson(strJson, type);
return datalist;
}
private static class ListParameterizedType implements ParameterizedType {
private Type type;
private ListParameterizedType(Type type) {
this.type = type;
}
@Override
public Type[] getActualTypeArguments() {
return new Type[] {type};
}
@Override
public Type getRawType() {
return ArrayList.class;
}
@Override
public Type getOwnerType() {
return null;
}
// implement equals method too! (as per javadoc)
}
相关参考:
Gson解析Json数组遇到的泛型类型擦除问题
前两天利用GSON解析JSON串,碰到了Java 泛型擦除的问题