【问题标题】:Why java lets me add a Box(Raw type) to a List<Box<? extends Item>>为什么 java 让我将 Box(Raw 类型) 添加到 List<Box<?扩展项目>>
【发布时间】:2021-07-24 06:19:28
【问题描述】:

此代码有效,我不明白列表如何添加原始类型框,我认为类型擦除会将类型设置为指定的范围。 注意:Paper 类不扩展 Bakery 类。

编辑:我的理解正确吗?编译器对原始框类型进行类型转换,以便可以将其添加到列表中?这仅在编译时有效吗?所以如果我试图在运行时获取值,它会抛出异常?

class Violator {

    public static List<Box<? extends Bakery>> defraud() {
        List<Box<? extends Bakery>> list = new ArrayList<>();
        Paper paper = new Paper();
        Box box = new Box<>();
        box.put(paper);
        list.add(box);
        return list;
    }
}
class Box<T> {
    void put(T item) { /* implementation omitted */ }
    T get() { /* implementation omitted */ }
}

【问题讨论】:

  • 您可以将原始类型分配给泛型类型。例如拥有List&lt;String&gt; names; List raw = new ArrayList();,您可以分配names = raw;。我的猜测是:因为在引入泛型类型之前,代码写成List getNames() { /*generates and returns list containing Strings with names*/ }。这让程序员可以像List&lt;String&gt; names = oldPojo.getNames(); 一样使用它(带有警告)——注意getNames() 返回raw List。因此,您还可以将您的Box box(原始)分配给Box&lt;? extends Bakery&gt;Box&lt;Bakery&gt;

标签: java generics type-erasure


【解决方案1】:

此代码确实会从Angelika Langer's blog 生成一个未经检查的转换警告,关于为什么允许它的原因

为什么允许使用原始类型?

为了方便与 非通用(遗留)代码。语言中允许使用原始类型 主要是为了促进与非泛型(遗留)的接口 代码。

如果,例如,你有一个非泛型的遗留方法,它需要一个 List 作为参数,可以传递参数化类型如 List&lt;String&gt; 到那个方法。相反,如果你有一个方法 返回一个 List ,您可以将结果分配给一个引用变量 输入 List&lt;String&gt; ,前提是您出于某种原因知道 返回的列表实际上是一个字符串列表。

您的答案在于相反,如果您有一个返回List 的方法,您可以将结果分配给List&lt;String&gt; 类型的引用变量。在您的情况下,您可能有一个返回 Box 的旧方法

 // Legacy code
 private Box getBox(){
     // returns a Box which satisfy the Box<? extends Bakery>
 }

即使返回的结果可能满足约束Box&lt;? extends Bakery&gt;,也无法完全确定,因此允许您将该框添加到您的列表中

【讨论】:

  • 为什么不使用 Java 语法而不是“字符串列表”?
  • 没有显示在引用的文本中,我懒得尝试反引号。谢谢你激励我
猜你喜欢
  • 1970-01-01
  • 2013-09-22
  • 1970-01-01
  • 2015-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-15
  • 1970-01-01
相关资源
最近更新 更多