当前位置: 首页 > 面试题库 >

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

金飞
2023-03-14
问题内容

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

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通用为上面的示例代码中未列出的另一种方法。我的问题是为什么不能做到上述几点的教育。


问题答案:

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

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

来自(优秀的)Java Generics
FAQ

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

原始类型的方法或构造html" target="_blank">函数具有在类型擦除后将具有的签名。

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

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

Enum<T extends Enum<T>>

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



 类似资料:
  • 编译时,此代码将产生以下+错误: 问题是访问中的类型T与列表中的T不相同。如何修复此编译问题?

  • 我想说得具体一点。我有一个名为Result的类和一个名为Result的派生类 这些类在方法中用作返回类型。为此,我创建了这个helper类: 正如您所看到的,上面的代码对于成功有两种返回类型,一种是如果您不想返回任何东西,另一种是如果您想返回一些东西,但是失败的结果永远不会返回什么东西。这是不必要的,只是一个错误消息。这使我想到以下问题:当我想创建一个可以使用返回类型返回Success,而不使用返

  • 问题内容: 背景 我曾经写过这种方法: 应该这样称呼它: 这很好用(尽管我在研究当前容易出错的问题时在这里的答案中已经看到)。 目前的情况 无论如何,现在我正在编写以下代码(在扩展javax.servlet.jsp.tagext.TagSupport的类中): 目的是可以这样称呼: 我的评估方法中的代码显然不起作用。的第二个参数应该是Class对象。这导致我: 我的问题 如何获得通用(返回)类型的

  • 如何获取这个类的类型?对于上下文,我使用ModelMapper,我需要类类型T从S转换为T。 背景: 我已经尝试了N种方法,其中我放置了“//一些方法来获取类型”,但没有任何效果。例如: 或

  • 对于一堆带有泛型的包装类,我的继承结构遇到了一些麻烦。这基本上是结构: 这将与当前代码一起编译和工作,但是,这似乎很危险。如果调用方像这样使用这个方法:,它将很好地编译,但是如果findMiddle尝试返回SubBWrapper,则在运行时会有一个ClassCastException。我以为行得通却行不通的是: 所以我的问题基本上是,有没有正确的方法来编写编译、运行并遵循最佳实践的方法findMi