小编典典

对泛型类的非泛型引用会导致非泛型返回类型

java

我有一个旧类,该类本身不是泛型,但其方法返回类型之一使用泛型:

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() { ... }
}

然后继续使用对的非泛型引用ThinggetStuff()不再返回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通用为上面的示例代码中未列出的另一种方法。我的问题是为什么不能做到上述几点的教育。


阅读 214

收藏
2020-11-16

共1个答案

小编典典

好吧,请两个,我误解了您的问题。

当您使用delcare Thing(称为 原始类型 )而不是Thing<?>参数化类型
)时,Java编译器会剥离所有泛型参数,即使是(如您的情况),方法的泛型也与方法的泛型无关。类。

来自(优秀的)Java Generics
FAQ

我可以像其他类型一样使用原始类型吗?

原始类型的方法或构造函数具有在类型擦除后将具有的签名。

这个看似轻率且不引人注意的句子描述了所讨论的行为。您将其Thing用作原始类型,因此返回类型为Collection(not
Collection<String>),因为这是类型擦除后的类型。

困惑?不奇怪。只需查看该常见问题解答的大小即可。大概有大约三个人了解Java泛型的全部含义。只要考虑一下我最喜欢的JDK声明:

Enum<T extends Enum<T>>

(在FAQ中也有对此的解释)。

2020-11-16