I'm using Guava TypeToken class in my project, but I'm getting an unexpected result.
I have 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();
}
}
So if I instantiate an object via new MyGenericClass<String>()
and then invoke getRecordType()
I expect to get java.lang.String
, instead I'm getting java.lang.Object
.
But, if I extend generic class:
public class MyStringImpl extends MyGenericClass<String> {
// ...
}
and instantiate this new class: new MyStringImpl()
then I get the correct result.
Why is this happening? Is this the expected behaviour of TypeToken
?
To add some boring details to Ian's answer: It would be nice if TypeToken
worked the way you expected, but this is impossible. When you declare
public class MyGenericClass<T> implements MyInterface {...}
the JVM sees something like
public class MyGenericClass<Object> implements MyInterface {...}
due to erasure.
But when you declare
public class MyStringImpl extends MyGenericClass<String> {...}
then in the definition of MyStringImpl
the generics used are recorded and can be obtained via Class#getGenericSuperclass()
. That's (a part of) the magic behind TypeToken
.
To make this work you need the same anonymous subclass trick when you instantiate MyGenericClass
:
new MyGenericClass<String>() {}
If you do that then you will get String
returned by getRecordType
. The reason why this is necessary is explained in the JavaDocs for that TypeToken
constructor .
Clients create an empty anonymous subclass. Doing so embeds the type parameter in the anonymous class's type hierarchy so we can reconstitute it at runtime despite erasure.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.