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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With