【问题标题】:Gson illegal type variable referenceGson 非法类型变量引用
【发布时间】:2017-01-09 18:38:39
【问题描述】:

我有一个类定义为:

public class Calls<T extends Object>

在这个类中有一个方法 doRequest,它为 Gson 请求创建一个 TypeToken(来自 com.google.json.reflect)。

java.lang.reflect.Type type = new TypeToken<HandlerResponse<T>>(){{}}.getType();

其中HandlerResponse 是一个简单的模型类,包含以下属性:

private Map detail;

private transient T data;

private transient int count = 0;

private String status;

我在 Android Studio 上遇到的异常是:

FATAL EXCEPTION: main
Process: PID: 32628
java.lang.AssertionError: illegal type variable reference
    at libcore.reflect.TypeVariableImpl.resolve(TypeVariableImpl.java:111)
    at libcore.reflect.TypeVariableImpl.getGenericDeclaration(TypeVariableImpl.java:125)
    at libcore.reflect.TypeVariableImpl.hashCode(TypeVariableImpl.java:47)
    at java.util.Arrays.hashCode(Arrays.java:4153)
    at com.google.gson.internal.$Gson$Types$ParameterizedTypeImpl.hashCode($Gson$Types.java:479)
    at com.google.gson.reflect.TypeToken.<init>(TypeToken.java:64)
    at com.company.server.Calls$4.<init>(Calls.java:244)

在 TypeToken 的实例化时崩溃(我在想这可能会丢失 T 类,因为 Java 的类型擦除)。

我将Calls 的实例创建为:

Calls<com.company.model.beans.Model> calls = new Calls<>(){};

【问题讨论】:

  • 这个new TypeToken&lt;HandlerResponse&lt;T&gt;&gt;(){{}}.getType(); 不会像你想的那样。对应的Type 将反映类型变量T,而不是推断的类型。
  • 当您使用泛型类型参数实例化类型标记时,它对您没有多大帮助,因为T 在运行时不存在(类信息除外)。您不必在此处实例化类型令牌,而是从某处委托它(例如通过Calls 构造函数),从而在 调用站点 实例化类型令牌,例如Type stringHandlerResponseType = new TypeToken&lt;HandlerResponse&lt;String&gt;&gt;(){}.getType()new Calls(stringHandlerResponseType)。请注意,现在您有了一个 real 类型。顺便说一句,你有一个错字:{{}} 应该只是 {}
  • 你是正确的@LyubomyrShaydariv 正确的用法 i 与 {} (如在此 example 中),我按照你的建议做了,我在构造函数上移动了 TypeToken 对象,现在它可以工作了。

标签: java android generics gson type-erasure


【解决方案1】:

解决了,我修改实现如下:

public class Calls<T> {

    public Calls(Type type, Class classTypeResponse) {

        this.type = type;
        this.classTypeResponse = classTypeResponse;
    }

    doRequest(...) { ... }

    ...
}

我有一个classTypeResponse,因为我有一个回调系统,它为请求的对象返回正确的类类型。

我是这样称呼的:

Type type = new TypeToken<HandlerResponse<com.company.model.beans.Model>>(){}.getType();

Calls<com.company.model.beans.Model> calls = new Calls<>(type, com.company.model.beans.Model.class);

calls.doRequest(...);

T 在运行时不存在,Java 反射系统无法为TypeToken 推断出正确的类型。解决方案是创建不带泛型的 TypeToken 并将对象传递到您需要的地方。

【讨论】:

  • 顺便说一句,你可以把&lt;T extends Object&gt;写成&lt;T&gt;,因为T总是暗示“按对象扩展”。
  • @LyubomyrShaydariv 是的,当我试图解决问题时,它一直存在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-13
  • 1970-01-01
  • 1970-01-01
  • 2017-11-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多