我在我的项目中使用了番石榴TypeToken类,但是我得到了一个意想不到的结果。
我有MyGenericClass<T>
public class MyGenericClass<T> implements MyInterface {
private TypeToken<T> recordType;
public MyGenericClass(String name) {
this.recordType = new TypeToken<T>(getClass()) {};
// ...
}
// ...
@SuppressWarnings("unchecked")
protected Class<T> getRecordType() {
return (Class<T>) recordType.getRawType();
}
}因此,如果我通过new MyGenericClass<String>()实例化一个对象,然后调用getRecordType(),我希望得到java.lang.String,而不是得到java.lang.Object。
但是,如果我扩展泛型类:
public class MyStringImpl extends MyGenericClass<String> {
// ...
}并实例化这个新类:new MyStringImpl(),然后得到正确的结果。
为什么会发生这种情况?这是TypeToken的预期行为吗?
发布于 2014-09-30 15:27:13
要完成这项工作,实例化MyGenericClass时需要使用相同的匿名子类技巧。
new MyGenericClass<String>() {}如果这样做,那么String将由getRecordType返回。在构造函数中解释了为什么这是必要的。
客户端创建一个空的匿名子类。这样做将类型参数嵌入到匿名类的类型层次结构中,这样我们就可以在运行时重新设置它,尽管删除了它。
发布于 2014-09-30 23:49:08
在伊恩的回答中添加一些无聊的细节:如果TypeToken按你预期的方式工作,那就太好了,但这是不可能的。当你宣布
public class MyGenericClass<T> implements MyInterface {...}JVM看到的情况如下
public class MyGenericClass<Object> implements MyInterface {...}因为擦除了。
但当你宣布
public class MyStringImpl extends MyGenericClass<String> {...}然后,在MyStringImpl的定义中,对所使用的泛型进行记录,并通过Class#getGenericSuperclass()获得。这是TypeToken背后的神奇之处。
https://stackoverflow.com/questions/26124151
复制相似问题