【问题标题】:Java Generics: Array CastingJava 泛型:数组转换
【发布时间】:2016-03-06 11:51:56
【问题描述】:

我想强制转换一个包含泛型类型的对象数组,以供严格内部使用。


对象:

private class Node<T>
{
    T element;
    int prior;

    public Node(T element, int prior)
    {
        this.element=element;
        this.prior=prior;
    }

}

数组:

private Node<E>[] elements;

演员:

public PriorityQueue()
{   
  elements = (Node<E>[])new Object[capacity]; // ClassCastException
}

为什么我会得到 ClassCastException?

【问题讨论】:

  • 因为 Object[] 不是 Node[]。

标签: java arrays generics casting


【解决方案1】:

这里接受的解决方案应该可以解决问题:

casting Object array to Integer array error

您不能将 Object[] 直接转换为 Node[],但可以使用 Arrays.copyOf() 创建正确类型的副本。唯一的缺点是这涉及复制,但它是 Java:如果您希望它不慢,您就不会对自己这样做;)

【讨论】:

  • 实际上 Arrays.copyOf 使用 Sytsem.arraycopy 使用本机代码。 java在性能方面也接近C:benchmarksgame.alioth.debian.org/u64q/java.html
  • 是的,副本会很便宜,因为 arraycopy 并不可怕(尽管它会进行边界检查,这是一个很小的开销)。另一方面,我们需要这个副本的唯一原因是因为 Java 的类型系统存在缺陷。
【解决方案2】:

强制转换不起作用的原因是Node&lt;E&gt; 的类型擦除适用于Node 内部的E,但不适用于Node&lt;E&gt; 的数组。

类型擦除可以让您将Node&lt;E&gt; 转换为Node&lt;Object&gt;,因为所有Node&lt;E&gt;s 都是Node&lt;Object&gt;。同样,它可以让您将Node&lt;E&gt;[] 转换为Node&lt;Object&gt;[] 并返回,因为这些数组共享相同的底层类型——即Node&lt;Object&gt;

但是,当您处理数组时,类型擦除不起作用。对象数组仍然是对象数组,Java 有足够的元数据来了解它。

你有几种方法可以解决这个问题:

  • Node&lt;E&gt;[] 切换到 ArrayList&lt;Node&lt;E&gt;&gt; - 数组列表具有相似的占用空间和访问时间,并且是通用的
  • 使用来自 this Q&A 的解决方案 - 类型安全的解决方案需要传递 Class&lt;E&gt;

【讨论】:

    猜你喜欢
    • 2021-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-28
    • 2013-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多