Java泛型:数组转换

3
我愿意为内部使用而投射包含泛型类型的对象数组。

该对象:

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错误?

2
因为 Object[] 不是 Node[]。 - Oliver Charlesworth
2个回答

1

这里的被接受的解决方案应该能解决问题:

将对象数组转换为整数数组错误

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


实际上Arrays.copyOf使用了System.arraycopy,而System.arraycopy使用了本地代码。此外,Java在性能方面与C语言非常接近:https://benchmarksgame.alioth.debian.org/u64q/java.html - Cyril
是的,复制将会很便宜,因为arraycopy并不糟糕(尽管它会有一些边界检查,这是一个微小的开销)。另一方面,我们需要进行这个复制的唯一原因是Java类型系统中存在缺陷。 - Chris Kitching

0

转换失败的原因是 Node<E> 的类型擦除只适用于 Node 内部的 E,但不适用于 Node<E> 数组。

类型擦除允许您将 Node<E> 强制转换为 Node<Object>,因为所有的 Node<E> 在底层都是 Node<Object>。同样地,它也允许你将 Node<E>[] 强制转换成 Node<Object>[] 并且回弹,因为这些数组共享相同的基础类型,即 Node<Object>

然而,在处理数组时,类型擦除不起作用。对象数组仍然是对象数组,Java 有足够的元数据知道它们的类型。

您有几种解决此问题的方法:

  • Node<E>[] 切换到 ArrayList<Node<E>> - 数组列表具有类似的占用空间和访问时间,并且是泛型的
  • 使用 这个 Q&A 中的解决方案 - 类型安全的解决方案需要传递 Class<E>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接