我有一个遗留类,该类本身不是泛型,但它的一个方法返回类型使用泛型:
public class Thing {
public Collection<String> getStuff() { ... }
}
getStuff()
使用泛型返回字符串集合。因此我可以遍历 getStuff()
并且无需将元素转换为 String
:
Thing t = new Thing();
for (String s: t.getStuff()) // valid
{ ... }
但是,如果我改变 Thing
本身是通用的,但保持其他一切相同:
public class Thing<T> {
public Collection<String> getStuff() { ... }
}
然后继续使用对 Thing
的非通用引用, getStuff()
不再返回 Collection<String>
而是返回一个非类型化的 Collection
.因此客户端代码无法编译:
Thing t = new Thing();
for (String s: t.getStuff()) // compiler complains that Object can't be cast to String
{ ... }
这是为什么?解决方法是什么?
我的猜测是,通过使用对泛型类的非泛型引用,Java 关闭了整个类的所有泛型。这很痛苦,因为现在我通过将 Thing 设为通用来破坏了我的客户端代码。
编辑: 我正在为上述示例代码中未列出的另一种方法制作 Thing 通用方法。我的问题是关于为什么不能完成上述操作的教育问题。
最佳答案
好吧,我误解了你的问题。
当你删除 Thing
(这称为原始类型)而不是Thing<?>
(参数化类型)Java 编译器会删除所有泛型参数,即使(如您的情况)方法的泛型类型与类的泛型类型无关。
来自(优秀)Java Generics FAQ :
Can I use a raw type like any other type?
Methods or constructors of a raw type have the signature that they would have after type erasure.
这句看似无关紧要且不引人注意的句子描述了相关行为。您正在使用 Thing
作为原始类型,因此返回类型为 Collection
(不是 Collection<String>
)因为这是类型删除后的类型。
困惑?不奇怪。看看那个常见问题解答的大小。地球上大概只有三个人了解 Java 泛型的全部含义。想想我最喜欢的 JDK 声明:
Enum<T extends Enum<T>>
(在常见问题解答中也有对此的解释)。
关于java - 对泛型类的非泛型引用导致非泛型返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/449103/