【问题标题】:array of parameterized types参数化类型数组
【发布时间】:2012-03-21 11:23:15
【问题描述】:

我无法确定以下 RHS 预期的类型参数

ArrayList<Pair<ParseNode,ParseNode>>[] nodes = new ArrayList[indexes.length];

为什么&lt;Pair&lt;ParseNode,ParseNode&gt;&gt; 的副本不合法?

【问题讨论】:

    标签: java generics


    【解决方案1】:

    Java 不支持泛型数组。数组是协变的,泛型不是。这意味着如果类 A 扩展类 B,则 A[] 也是 B[]。和代码

    A[] a = new A[10];
    B[] b = a;
    

    是合法的。

    但是对于泛型来说就不一样了。即使 T 扩展了 X,您也无法将 Foo&lt;T&gt; 分配给 Foo&lt;X&gt;。因此无法保证 Foo&lt;T&gt;[] 的元素类型安全。

    编辑 对不起,我只是链接出去,但我发现 Java theory and practice: Generics gotchas 文章,它比我想象的更好地解释了有关数组协方差的一切。

    【讨论】:

    • 确实如此。关于这一事实的更多信息在这里:stackoverflow.com/questions/529085/…
    • 很遗憾我开始回答这个问题。理解是好的,但是当你不能清楚地解释它时,它一文不值:) 现在我发现它还不清楚。
    【解决方案2】:

    具体参数化类型的数组本身就被破坏了。记住数组是协变的,数组类型检查是一个运行时操作。在运行时,所有泛型都已被类型擦除,因此数组存储检查无法区分 &lt;Pair&lt;ParseNode, ParseNode&gt;&gt;&lt;Pair&lt;BigInteger,IOException&gt;&gt;

    泛型的基本约定是“我,编译器,承诺如果您编写的代码不会产生警告,您将永远不会在运行时遇到类转换异常。”

    编译器也不能向您保证,如果将不是 ArrayList&lt;Pair&lt;ParseNode,ParseNode&gt;&gt; 的东西放入该数组中,它将能够给您一个编译时错误。如果您添加了错误的类型,运行时系统也不能保证您将获得 ArrayStoreException(就像语言规范所说的那样),而不是稍后在您将其取出时获得 ClassCastException。 (第二部分真的是为什么它实际上是非法的,而不仅仅是一个警告,它会导致一个不符合语言规范的数组。)

    因此它不允许您以这种方式声明它们并强制您承认“不安全”警告。这样它就说“我告诉过你,我不能保证不会因为使用这个数组而出现任何类转换异常,你必须确保在这里只放正确的东西。”

    【讨论】:

      【解决方案3】:

      不要使用数组。使用另一个 ArrayList。

      ArrayList<List<Pair<ParseNode,ParseNode>>> listOfLists = new ArrayList<List<Pair<ParseNode,ParseNode>>>();
      
      listOfLists.add(new ArrayList<<Pair<ParseNode,ParseNode>>());
      

      【讨论】:

        猜你喜欢
        • 2012-02-09
        • 1970-01-01
        • 2013-05-04
        • 1970-01-01
        • 2011-11-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多