Question: Replacing TypeToken from Guava with Gson ?
See original GitHub issueI am currently trying to refactor a project to avoid having to use guava as a dependency. I was using it mainly for reflection related features, but in most case I could find an altenative.
However, there is one case left I cannot fix for now: I try to retrieve the class of a generic parameter of the current class.
It works fine using Guava since the Type returned by TokenType can be casted to Class.
Guava:
(Class<I>) new com.google.common.reflect.TypeToken<I>(getClass()) {}.getType();
I attempted to substitute this call using the TypeToken from Gson instead, but apparently the information about I is lost and there result of this call is a TypeVariable than is kept as a Class<Object> after executing:
Gson:
(Class<I>) com.google.gson.reflect.TypeToken<I>() {}.getType();
As far as I can tell the getClass() parameter is a clue to why context is not kept. When I use Guava with the same signature:
(Class<I>) com.google.gson.reflect.TypeToken<I>() {}.getType();
I get this error message:
java.lang.IllegalStateException: Cannot construct a TypeToken for a type variable. You probably meant to call new TypeToken(getClass()) that can resolve the type variable for you. If you do need to create a TypeToken of a type variable, please use TypeToken.of() instead.
I see Gson also as a (package protected) constructor using a Type as argument.
Is there a way to obtain the class of a Generic Parameter using Gson only ?
Issue Analytics
- State:
- Created 5 years ago
- Comments:6 (3 by maintainers)
Top GitHub Comments
I missed that point 3 months ago, but:
(IF I understood your question 100% clear) You can’t do this in your case, because you’re trying to obtain the actual class while can obtain a type variable only (at least this is what I can see in your original question). For example, suppose you want to have your code play nice with generics and type safety, and you’re deciding to get rid of Gson
TypeToken
completely, then you could implement a simple type-safe wrapper:Now suppose you have a quick test like this:
The code above produces
whose classes are
class java.lang.Class
,class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
, andclass sun.reflect.generics.reflectiveObjects.TypeVariableImpl
(for example). Note that each of them are implemented differently therefore have different classes. In the case of<ANY>
you can’t have an actual type when invoking the method with different type parameters. It won’t work unless you let it know the actual type somehow. For example:This results in
The
T
implementation is a simple wrapper demonstrating why type tokens can work and how they obtain the type information. Additionally,Class<I>
cannot work here becauseClass
only represents a class loaded by a class loader in JVM, these classes cannot be actually parameterized (but can can extend parameterized classes and this makes the type tokens work + and can hold type variable being not able to work as well as thethisCannotWork()
method can’t).Consider type tokens only as a type safe alternative for holding types your application work with (this makes methods like
thisCanWork()
control what types are used as “in” and “out”), however this is just a wrapper around aType
instance that actually represents a type, not class. In my comment above I marked thatType
is the essential part here, and it does not really matter where you can obtain it from: either construct it yourself just implementing proper interfaces, or askjavac
to put type information into the subclass’ superclass metadata and then use type token mechanism.Sorry for a long and vague answer, I hope it can shed some more light on how types and type tokens work.
Thank you for the detailed explanation. This is actually clearer in my mind.