cb.*_*cb. 4 java arrays generics
在这种情况下哪种是最佳做法?我想要一个与原始类型和长度相同的未初始化数组.
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...
}
Run Code Online (Sandbox Code Playgroud)
谢谢,CB
AnyType[] anotherArray = (AnyType[])java.lang.reflect.Array.newInstance(
someArray.getClass().getComponentType(), someArray.length);
Run Code Online (Sandbox Code Playgroud)
数组和泛型并不能很好地混合.这是因为数组是协变的,而泛型不是.让我给你举个例子:
public static void main(String args[]) {
foo(new Float[1]);
}
public static void foo(Number[] n) {
n[0] = 3;
}
Run Code Online (Sandbox Code Playgroud)
该代码编译但会导致ArrayStoreException.
因此,重新创建该数组时遇到的问题是它可能不是一个数组,AnyType但它可能是一个子类AnyType.你当然可以使用someArray.getClass()和创建带反射的数组.
然而,整体主题是你应该偏爱List数组,因为Lists没有相同的问题.将代码更改为:
public static void main(String args[]) {
foo(new ArrayList<Float>());
}
public static void foo(List<Number> list) {
list.add(3);
}
Run Code Online (Sandbox Code Playgroud)
代码将无法编译,这是一个更好的结果.
一个很好的参考是看看如何<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);
//...
Run Code Online (Sandbox Code Playgroud)
所以该技术使用:
Class<?> Class.getComponentType()
返回
Class表示数组的组件类型.如果此类不表示此方法返回的数组类null.
Object Array.newInstance(Class<?> componentType, int... dimension)
创建具有指定组件类型和尺寸的新数组.
最后,简单的老(T[])演员.
如果你绝对必须创建一个"通用"数组,那么传递instanceof T[]和使用反射来实例化另一个数组的技术就是Java Collections Framework的例子.
但是,您还必须质疑是否确实需要此类功能.
从Effective Java 2nd Edition:第25项:首选列表到数组:
总之,数组和泛型具有非常不同的类型规则.数组是协变的和具体化的,泛型是不变的和被删除的.因此,数组提供运行时类型安全性,但不提供编译时类型安全性,反之亦然.一般来说,数组和泛型不能很好地混合.如果你发现自己混合它们并得到编译时错误和警告,你的第一个冲动应该是用列表替换数组.
您应该阅读整个项目,以便更全面地处理该主题.