2

可能重复:
在 Java 中创建泛型数组

我想将一个通用的对象数组修剪到只有第一个 len 元素。这似乎应该工作:

@SuppressWarnings("unchecked")
public static <T> T[] trimArray(T[] data, int len){
    T[] result = (T[]) new Object[len];
    System.arraycopy(data, 0, result, 0, len);
    return result;
}

但是如果我做类似的事情,它会抛出一个 ClassCastException

public class Foo{

    double f;

    public Foo(double f){
    this.f = f;
    }

}

public static void main(String[] args){

    Foo[] A = new Foo[10];
    A[0]= new Foo(1);
    A[1]= new Foo(2);
    A[2]= new Foo(3);
    Foo[] B = trimArray(A, 3);

}

我不明白为什么这不起作用,但是在泛型类中的 java 泛型转换中类似的东西

4

2 回答 2

11

JDK 已经为此内置了一个:

Foo[] B = Arrays.copyOf(A, 3);

Javadoc(从 1.6 开始)

但是请注意,如果源数组长度小于所需长度,它也会扩展数组(用 s 填充)。null您可以使用以下方法轻松解决此问题:

Foo[] B = Arrays.copyOf(A, Math.min(3, A.length));
于 2012-12-30T17:56:49.917 回答
1

发生这种情况是因为数组是协变的,这意味着您可以自由地将子类型的数组视为超类型的数组,但反之则不然。

可以做什么,虽然它是一个丑陋的黑客,是返回一个Object[]然后将每个元素转换为T(数组中的实际元素是协变的,但数组本身不是),但我强烈建议不要这样做。

使用其他答案中推荐的内置函数,例如Arrays.copyOf.

如果您想知道为什么,那是因为这很容易破坏类型安全。

例如:

Object[] bla = new Object[10];
bla[0] = new Integer(2);
bla[1] = "stillanObject";

你有一个对象数组,完全有效。

现在你把它转换成一个字符串数组......

return (String[])bla;

并且地狱将在 JVM 上被释放,您实际上将拥有一个应该是String包含StringInteger对象类型的数组!\

类型安全是一件好事。

更新:

只是为了添加更多细节,您可以强制String[]转换为Object[],但是ArrayStoreException如果您尝试存储任何不是String(或原始数组类型)的东西,这可能会发生。虽然读取原始数组Object[]是完全安全的。

于 2012-12-30T18:01:58.763 回答