简短的答案是,您需要移动
TypeTokenout 的创建,在创建标记()时
Executor将
Tin
绑定,然后将类型标记传递给构造函数。
Response<T>``new TypeToken<Response<Language>>(){}``Executor长答案是:
类型上的泛型通常在运行时删除,除非使用泛型参数绑定 编译 类型。在这种情况下,编译器会将泛型类型信息插入已编译的类中。在其他情况下,这是不可能的。
因此,例如,请考虑:
List<Integer> foo = new ArrayList<Integer>();class IntegerList extends ArrayList<Integer> { ... }List<Integer> bar = new IntegerList();在运行时,Java 知道
bar包含整数,因为
Integer类型是
ArrayList在编译时绑定的,因此泛型类型信息保存在
IntegerList类文件中。但是,的通用类型信息
foo已删除,因此在运行时实际上不可能确定
foo应该包含
Integer。
因此经常会出现这样的情况,即在正常情况下会在运行时将其擦除的情况下,例如在GSON中解析JSON数据的情况下,我们需要通用类型信息。在这些情况下,我们可以利用这样的事实,即类型信息在编译时
IntegerList通过使用类型标记(在上面的示例中)进行绑定而得以保留,而这些标记实际上只是可以方便地存储泛型类型信息的微小匿名类。
现在到您的代码:
Type responseType = new TypeToken<Response<T>>() {}.getType();在您的
Executor类的这一行中,我们创建一个匿名类(从继承
TypeToken),其类型
Response<T>在编译时进行了硬编码(绑定)。因此,在运行时,GSON能够确定您需要的对象
Response<T>。但是它不知道是什么
T,因为您没有在编译时指定它!因此,GSON无法确定它创建
List的
Response对象的类型是什么,而只是创建了一个
StringMap。
这个故事的寓意是您需要
T在编译时指定它。如果
Executor要一般使用,则可能需要在客户端代码中在该类之外创建类型标记。就像是:
class Executor<T> { private TypeToken<Response<T>> responseType; private Response<T> response; public Executor(TypeToken<Response<T>> responseType) { this.responseType = responseType; } public void execute() { this.response = new Gson().fromJson(json, responseType.getType()); } public Response<T> getResponse() { return this.response; }}// client pre:Executor<Language> executor = new Executor<Language>(new TypeToken<Response<Language>>() { });executor.execute();List<Language> languages = executor.getResponse().getData();System.out.println(languages.get(0).alias); // prints "be"顺便说一句,我确实在我的机器上测试了以上内容。
抱歉,时间太长!



