【问题标题】:Caused by: java.lang.ClassCastException: libcore.reflect.ParameterizedTypeImpl cannot be cast to java.lang.Class when use Generic Type原因:java.lang.ClassCastException:libcore.reflect.ParameterizedTypeImpl 在使用通用类型时无法转换为 java.lang.Class
【发布时间】:2016-01-26 07:30:40
【问题描述】:

我做了一个类扩展 AsyncTask 来解析 Json 使用 Gson,因为输入可以是多种类型的类我使用泛型类型:

public class ApiResponse<T> extends AsyncTask...

我需要知道 T 的类类型才能通过 Gson:

(1)

Class<T> clazz =
    (Class<T>)((ParameterizedType)
        getClass().getGenericSuperclass())
    .getActualTypeArguments()[0];

new Gson().fromJson(reader, clazz);

但是,这里的 T 可以是一个有很多类型的类,所以有时我会通过类:

(2)

public class DataMessage<T> implements Serializable{...}

由于这些类具有这种格式,我收到了一个异常原因:

java.lang.ClassCastException: libcore.reflect.ParameterizedTypeImpl cannot be cast to java.lang.Class

在 (1) 处

在这种情况下我该怎么办?

更新:

public class DataMessage<T> implements Serializable{

    @SerializedName("pagination")
    private Pagination pagination;
    @SerializedName("meta")
    private Message meta;
    @SerializedName("data")
    private T data;

    public DataMessage(T data) {
        this.data = data;
    }

    public Pagination getPagination() {
        return pagination;
    }

    public void setPagination(Pagination pagination) {
        this.pagination = pagination;
    }

    public Message getMeta() {
        return meta;
    }

    public void setMeta(Message meta) {
        this.meta = meta;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public class Pagination {
        @SerializedName("next_max_tag_id")
        public String nextMaxTagId;
        @SerializedName("deprecation_warning")
        public String deprecationWarning;
        @SerializedName("next_max_id")
        public String nextMaxId;
        @SerializedName("next_min_id")
        public String nextMinId;
        @SerializedName("min_tag_id")
        public String minTagId;
        @SerializedName("next_url")
        public String nextUrl;
    }

    public class Message {
        @SerializedName("error_type")
        public String errorType;
        @SerializedName("code")
        public int code;
        @SerializedName("error_message")
        public String error_message;
    }
}

【问题讨论】:

  • 能否将 Json 对象添加到问题中?
  • 嗨,@AndreaCatania 先生,请看我更新了。
  • 我参考了@yole 链接,发现 Gson 的输出是 LinkedTreeMap 无法转换为我的数据类型
  • 如果可以粘贴 JSON 对象

标签: java android generics exception casting


【解决方案1】:

当我需要使用 Gson 解析带有特定类的 JSON 时,我使用 GsonBuilder 这种方式

GsonBuilder gsonBuilder = new GsonBuilder();

gsonBuilder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
   public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        try{
           return new Date( json.getAsJsonPrimitive().getAsLong()*1000L );
        }catch( Exception e ){
            return null;
        }

   }
});

Gson gson = gsonBuilder.create();

在您的情况下,我认为您可以通过这种方式简单地解析您的 JSON:

DataMessage<YourClass> dataMessage = gson.fromJson(yourJsonObj, DataMessage.class);

还有一点就是可以通过这种方式获取准确的Type

Type collectionType = new TypeToken<DataMessage<T>>() {}.getType();

但是当你反序列化这个时,你可能会得到一个糟糕的 Json...

最好的方法是使用类而不是 T,这样 Gson 就知道要序列化/反序列化什么

Type collectionType = new TypeToken<DataMessage<YourClass>>() {}.getType();

我为你找到了这个Deserializing Generic Types with GSON

【讨论】:

  • 问题是我的 DataMessage 类,我也使用通用类型,如果我使用其他类,则可以通过 clazz = (Class) ((ParameterizedType) getClass().getGenericSuperclass( )).getActualTypeArguments()[0];
  • 在解析T的类型之前能知道吗?
  • 我需要获取类来放置“...fromJson...”,因为我们不能使用 T.getClass 或 T.class
  • 是的,我在调用 AsyncTask 时输入了 T 类型,例如:new ApiResponse>>(context).execute....
  • 是的,如果我通过 DataMessage.class 修复 Gson.fromJson 中的类,结果很好。但是我的类 ApiResponse 接受所有类型,它禁止是 User 或 DataMessage ....
【解决方案2】:

假设您要反序列化 DataMessage&lt;T&gt; using a JsonReader 的列表。

public <T> T Gson::fromJson(JsonReader reader, Type typeOfT)

那么你有

..
import java.lang.reflect.Type; // make sure you add this import

class DataMessageList<T>
{
    public List<DataMessage<T>> list;

    public DataMessageList ()
    {
        list = null;
    }

    public void readJson (JsonReader reader)
    {
        Type TT = new TypeToken<ArrayList< DataMessage<T> >>(){}.getType();

        this.list = new Gson().fromJson(reader, TT);
    }
}

【讨论】:

  • 和我的回答有什么不同?
  • 如果你阅读了我所有的答案,我写的是:Type collectionType = new TypeToken>() {}.getType();
  • @AndreaCatania 不同之处在于导入,我的 sn-p 是连贯的。
【解决方案3】:

感谢@Andrea Catania 提供的有用帮助,

这里的问题是当我将((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 转换为Class 类型时,使用DataMessage&lt;T&gt; 类型它无法转换。

但是((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0] 的类型是Type,所以我不需要将其转换为Class,我将clazz 变量重新输入为Type(不是Class),问题已解决。

【讨论】:

  • 很高兴能帮助交配
猜你喜欢
  • 2015-04-19
  • 2011-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-22
  • 1970-01-01
  • 1970-01-01
  • 2020-10-23
相关资源
最近更新 更多