为什么Guava的TypeToken<T>.getRawType()返回Class<? super T>而不是Class<T>?

10

根据《Effective Java 第二版》,第28条:不要将通配符类型用作返回类型。与其为用户提供额外的灵活性,这会强制客户端代码使用通配符类型。

public final Class<? super T> getRawType()

我刚刚开始学习泛型通配符,以理解我正在编写的代码中最后一个未检查的类型转换警告,但我不理解为什么getRawType()返回通配符类型。

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();
}

我需要将 token.getRawType() 进行强制类型转换,因为它返回一个

Class<? super ? extends Base<C>>
2个回答

8
如果你有一个 TypeToken<ArrayList<String>>,并且想要获取 Class<ArrayList>(即原始类型),该怎么办呢?如果它返回 Class<T>,那么它将返回 Class<ArrayList<String>>,而不是你想要的 Class<ArrayList>。

1
感谢@newacct,这是我不理解的东西,但ArrayList<String>扩展ArrayList有道理。Class<? super T>描述了它返回的内容,尽管就客户端代码而言,它也可以返回Class<?>,因为您总是需要进行强制转换。 - MikeB

0

如果“token”的通用类型是Type类(即如果S在

TypeToken<S>

如果 S 是 java.lang.reflect.Type 类的实例,那么 TypeToken.getRawType() 将返回与 S 相关联的原始类型。它应该是一个 Class 对象,S 的父类。
请参阅 TypeToken 的源代码。
在某些情况下(例如具有多个边界的情况),实现的策略将不起作用,并且拥有原始类型是可以的:原始类型将是 Object.class。
例如,请参阅 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 {
...
}

我已经阅读了源代码,但仍然找不到返回 S 的父类的情况。我尝试了 new TypeToken<WildcardType>(){}.getRawType(),但它返回的是 WildcardType 类的一个实例,而不是任何父类。 - MikeB
2
请注意,您的 TypeToken 链接指向了 gson 版本。这里是 Guava 版本:http://code.google.com/p/guava-libraries/source/browse/guava/src/com/google/common/reflect/TypeToken.java - Paul Bellora

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接