如何创建新的AnyType []数组?

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

Dim*_*eou 7

AnyType[] anotherArray = (AnyType[])java.lang.reflect.Array.newInstance(
      someArray.getClass().getComponentType(), someArray.length);
Run Code Online (Sandbox Code Playgroud)

  • 应该指出的是,这会创建一个数组,其基类型与输入数组的基类型相同.这*不一定与编译器推断的泛型类型参数*相同. (3认同)

cle*_*tus 5

数组和泛型并不能很好地混合.这是因为数组是协变的,而泛型不是.让我给你举个例子:

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)

代码将无法编译,这是一个更好的结果.


pol*_*nts 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);
    //...
Run Code Online (Sandbox Code Playgroud)

所以该技术使用:

如果你绝对必须创建一个"通用"数组,那么传递instanceof T[]和使用反射来实例化另一个数组的技术就是Java Collections Framework的例子.

但是,您还必须质疑是否确实需要此类功能.

Effective Java 2nd Edition:第25项:首选列表到数组:

总之,数组和泛型具有非常不同的类型规则.数组是协变的和具体化的,泛型是不变的和被删除的.因此,数组提供运行时类型安全性,但不提供编译时类型安全性,反之亦然.一般来说,数组和泛型不能很好地混合.如果你发现自己混合它们并得到编译时错误和警告,你的第一个冲动应该是用列表替换数组.

您应该阅读整个项目,以便更全面地处理该主题.