我想将一般的对象数组修剪为只有第一个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;
}
但如果我执行类似
的操作,它会抛出ClassCastExceptionpublic 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
中有类似的功能答案 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
的数组,其中包含String
和Integer
个对象! \
类型安全是一件好事。
更新:
只是要添加一个详细信息,您可以将String[]
投射到Object[]
,但如果您尝试存储任何不是ArrayStoreException
的内容,这可能会产生String
}(或原始数组的类型)。将原始数组作为Object[]
读取是完全安全的。