java trim泛型数组

时间:2012-12-30 17:53:52

标签: java generics casting

  

可能重复:
  Creating generic arrays in 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 generic casting in generic classes

中有类似的功能

2 个答案:

答案 0 :(得分:11)

JDK已经内置了这个:

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

Javadoc(自1.6起)

但是请注意,如果源数组长度小于所需长度,它还将展开数组(用null填充)。您可以通过使用,例如:

轻松解决此问题
Foo[] B = Arrays.copyOf(A, Math.min(3, A.length));

答案 1 :(得分: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[]读取是完全安全的。