Why does Guava's TypeToken.getRawType() ret

2020-03-01 16:15发布

问题:

From Effective Java Second Edition, Item 28 : "Do not use wildcard types as return types. Rather than providing additional flexibility for your users it would force them to use wildcard types in client code."

public final Class<? super T> getRawType()

I've just been getting to grips with generic wildcards to understand the last unchecked cast warning I have in a piece of code I am writing and I don't understand why getRawType() returns a wildcard type.

class Base<T>{}
class Child<T> extends Base<T>{}

public <C> void test (TypeToken<? extends Base<C>> token) {
    Class<? extends Base<C>> rawType = (Class<? extends Base<C>>) token.getRawType();
}

I have to cast token.getRawType() as it returns a

Class<? super ? extends Base<C>>

回答1:

What if you have a TypeToken<ArrayList<String>> and you want to get Class<ArrayList> (that is the raw type). If it returned Class<T>, then it would return Class<ArrayList<String>> which is not Class<ArrayList> that you want.



回答2:

If the generic type of "token" is a Type class (i.e. if S in

TypeToken<S>

is a java.lang.reflect.Type class), then TypeToken.getRawType() will return the raw type associated to S. It shall be a Class object, parent of S.

See the source code of TypeToken.

In some cases (like having multiple bounds), the strategy implemented won't work and having a raw type is Ok: the raw type will be Object.class

See for instance MoreTypes:

public static Class<?> getRawType(Type type) {
...
} else if (type instanceof TypeVariable) {
  // we could use the variable's bounds, but that'll won't work if there are multiple.
  // having a raw type that's more general than necessary is okay  
  return Object.class;

} else {
...
}