java trim泛型数组

java trim泛型数组,java,generics,casting,Java,Generics,Casting,可能重复: 我想将一个通用的对象数组裁剪为仅第一个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; } 我不明白为什么这样做行

可能重复:

我想将一个通用的对象数组裁剪为仅第一个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;
}

我不明白为什么这样做行不通,但类似的事情在JDK中已经有了一个内置的:

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

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

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

发生这种情况是因为数组是协变的,这意味着您可以将子类型的数组视为超类型的数组,但事实并非如此

尽管这是一个难看的破解,但您可以做的是根据需要返回一个
对象[]
,然后将每个元素强制转换为
T
(数组中的实际元素是协变的,但数组本身不是),但我强烈建议不要这样做

使用其他答案中推荐的内置选项,如
Arrays.copyOf

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

例如:

Object[] bla = new Object[10];
bla[0] = new Integer(2);
bla[1] = "stillanObject";
您有一个对象数组,完全有效

现在,您将其转换为,比方说,一个字符串数组

return (String[])bla;
地狱将在JVM上释放,实际上您将拥有一个类型为
String
的数组,其中包含
String
Integer
对象\

类型安全是一件好事

更新:


只需再添加一个详细信息,您可以将
字符串[]
强制转换为
对象[]
,但如果您尝试存储任何非
字符串(或原始数组类型)的内容,则这可能会在
阵列存储异常中发生。将原始数组作为
Object[]
读取是完全安全的。

发布完整的堆栈跟踪。
Foo[]
数组与
Object[]
数组不同:您可以在第二个数组中存储任何您想要的内容,而只能在第一个数组中存储Foo实例。From WP:“协变:从专用类型转换(猫)到更一般的类型(动物):每只猫都是动物。“现在,你从更一般的(对象)转换到更特殊的(字符串)。并称之为协变。你确定吗?你是对的,我在那里切换了术语,应该是固定的。
return (String[])bla;