【问题标题】:How do I create a new AnyType[] array?如何创建一个新的 AnyType[] 数组?
【发布时间】:2011-02-09 12:17:17
【问题描述】:

在这种情况下,最佳做法是什么?我想要一个类型和长度与原始数组相同的未初始化数组。

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

【问题讨论】:

  • 为什么这个标签是“初学者”?

标签: java arrays generics


【解决方案1】:
AnyType[] anotherArray = (AnyType[])java.lang.reflect.Array.newInstance(
      someArray.getClass().getComponentType(), someArray.length);

【讨论】:

  • 需要指出的是,这会创建一个数组,其基类型与输入数组的基类型相同。这不一定与编译器将推断的泛型类型参数相同
  • 另请注意,输入“someArray”也是如此。创建的“anotherArray”可以像“someArray”一样安全地存储“AnyType”的实例。所以这段代码没有添加任何不存在的限制。
【解决方案2】:

数组和泛型并不能很好地混合。那是因为数组是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() 并使用反射创建数组。

然而,总体主题是你应该更喜欢Lists 而不是数组,因为Lists 没有相同的问题。将代码更改为:

public static void main(String args[]) {
  foo(new ArrayList<Float>());
}

public static void foo(List<Number> list) {
  list.add(3);
}

而且代码无法编译,这是一个更好的结果。

【讨论】:

    【解决方案3】:

    一个很好的参考是看看&lt;T&gt; 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);
        //...
    

    所以该技术使用:

    如果您绝对必须创建一个“通用”数组,那么这种传递 instanceof T[] 并使用反射实例化另一个的技术就是 Java Collections Framework 所示例的方式。

    但是,您还必须询问您是否真的需要这样的功能。

    来自Effective Java 2nd Edition第 25 条:优先使用列表而不是数组

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

    您应该阅读整篇文章以更全面地了解该主题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-21
      • 1970-01-01
      • 2021-09-09
      • 1970-01-01
      • 1970-01-01
      • 2012-12-16
      • 2011-03-23
      • 2021-04-11
      相关资源
      最近更新 更多