我有一个旧类,该类本身不是泛型,但其方法返回类型之一使用泛型:
public class Thing { public Collection<String> getStuff() { ... } }
getStuff()使用泛型返回字符串的集合。因此,我可以进行遍历,getStuff()而无需将元素强制转换为String:
getStuff()
String
Thing t = new Thing(); for (String s: t.getStuff()) // valid { ... }
但是,如果我将Thing自己更改为通用名称,但其他所有内容均保持不变:
Thing
public class Thing<T> { public Collection<String> getStuff() { ... } }
然后继续使用对的非泛型引用Thing,getStuff()不再返回Collection<String>,而是返回非类型Collection。因此,客户端代码无法编译:
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通用为上面的示例代码中未列出的另一种方法。我的问题是为什么不能做到上述几点的教育。
好吧,请两个,我误解了您的问题。
当您使用delcare Thing(称为 原始类型 )而不是Thing<?>( 参数化类型 )时,Java编译器会剥离所有泛型参数,即使是(如您的情况),方法的泛型也与方法的泛型无关。类。
Thing<?>
来自(优秀的)Java Generics FAQ:
我可以像其他类型一样使用原始类型吗?
原始类型的方法或构造函数具有在类型擦除后将具有的签名。
这个看似轻率且不引人注意的句子描述了所讨论的行为。您将其Thing用作原始类型,因此返回类型为Collection(not Collection<String>),因为这是类型擦除后的类型。
困惑?不奇怪。只需查看该常见问题解答的大小即可。大概有大约三个人了解Java泛型的全部含义。只要考虑一下我最喜欢的JDK声明:
Enum<T extends Enum<T>>
(在FAQ中也有对此的解释)。