在这种情况下哪种方法最好?我想要一个与原始类型和长度相同的未初始化数组。
public static <AnyType extends Comparable<? super AnyType>> void someFunction(AnyType[] someArray) {
AnyType[] anotherArray = (AnyType[]) new Comparable[someArray.length];
...or...
AnyType[] anotherArray = (AnyType[]) new Object[someArray.length];
...some other code...
}
谢谢, CB
答案 0 :(得分:7)
AnyType[] anotherArray = (AnyType[])java.lang.reflect.Array.newInstance(
someArray.getClass().getComponentType(), someArray.length);
答案 1 :(得分:5)
阵列和泛型并不能很好地混合。这是因为数组是covariant而泛型不是。让我举个例子:
public static void main(String args[]) {
foo(new Float[1]);
}
public static void foo(Number[] n) {
n[0] = 3;
}
该代码编译但会产生ArrayStoreException
。
因此,重新创建该数组时的问题是它可能不是AnyType
的数组,但它可能是AnyType
的子类。您当然可以使用someArray.getClass()
并使用反射创建数组。
但总体主题是你应该支持List
s而不是数组,因为List
没有相同的问题。将代码更改为:
public static void main(String args[]) {
foo(new ArrayList<Float>());
}
public static void foo(List<Number> list) {
list.add(3);
}
代码将无法编译,这是一个更好的结果。
答案 2 :(得分:5)
一个很好的参考是看<T> T[] Collection.toArray(T[])
:
AbstractCollection
public <T> T[] toArray(T[] a) {
// Estimate size of array; be prepared to see more or fewer elements
int size = size();
T[] r = a.length >= size ? a :
(T[])java.lang.reflect.Array
.newInstance(a.getClass().getComponentType(), size);
//...
所以该技术使用:
Class<?> Class.getComponentType()
返回表示数组的组件类型的
Class
。如果此类不表示数组类,则此方法返回null
。
Object Array.newInstance(Class<?> componentType, int... dimension)
创建具有指定组件类型和尺寸的新数组。
最后,普通老(T[])
演员。
如果你绝对必须创建一个“通用”数组,那么这种传递instanceof T[]
并使用反射来实例化另一个的技术就是Java Collections Framework的例子。
但是,您还必须质疑确实是否需要此类功能。
来自 Effective Java 2nd Edition :第25项:首选列表到数组:
总之,数组和泛型具有非常不同的类型规则。数组是协变的和具体化的,泛型是不变的和被删除的。因此,数组提供运行时类型安全性,但不提供编译时类型安全性,反之亦然。一般来说,数组和泛型不能很好地混合。如果你发现自己混淆它们并得到编译时错误和警告,你的第一个冲动应该是用列表替换数组。
您应该阅读整个项目,以便对该主题进行更全面的处理。