【问题标题】:Why is the declaration of the array of generic type correct?为什么泛型类型数组的声明是正确的?
【发布时间】:2015-07-01 08:30:35
【问题描述】:

我们不能创建泛型类型的数组,这是众所周知的事实,所以我不会在这里提供对 JLS 的正式引用。但是我们可以声明这样的数组如下:

static <E> void reduce() {
    List<Integer>[] arr; //compiles fine
    E[] avv;             //compiles fine 
    avv = new E[10];       //doesn't compile
    arr = new List<Integer>[10]; //doesn't compile
}

有人知道这种声明的原因吗?

【问题讨论】:

  • 如果你不能声明一个泛型数组(作为变量、字段或方法参数),那么一个类怎么能使用泛型呢?

标签: java arrays generics


【解决方案1】:

首先,我假设你的意思是

avv = new E[2];             //doesn't compile
arr = new List<Integer>[2]; //doesn't compile

在方法的最后两行。您必须在创建新数组时指定数组的大小。但是,代码仍然无法编译。

数组早于泛型。从 Java 的第一个版本开始就存在数组,而泛型仅在 1.5 版中添加。为了不破坏旧代码,Java 设计者决定在运行时删除泛型类型:在运行时,类型参数被其上限替换。在您的情况下,在运行时,EObject 相同。不知道E到底是哪种类型。

这是一个问题,因为数组元素类型在运行时没有被擦除。 Integer[]String[] 是不同的类型,即使在运行时也是如此。如果你写new E[2],Java 运行时不知道它必须创建什么样的数组。它可以是String[]Integer[],或任何其他数组类型。因此,您不能使用通用元素创建新数组。

仍然允许具有泛型元素的数组作为类型,主要是为了在方法参数中使用它们:

<E> E doSomething(E[] param) { ... }

实际的数组是在程序的另一部分创建的,它的类型是已知的。您可以使用

调用此方法
String result = doSomething(new String[2]);

例如。

【讨论】:

    【解决方案2】:

    它允许您将泛型类型的数组作为方法参数传递。

    例如:

    public class Foo<T>
    {
        public void bar (T[] arr) {}
    }
    
    ...
    
    Foo<String> foo = new Foo<String>();
    String[] arr = {"aa","bb");
    foo.bar (arr);
    

    如果不允许使用T[],则方法签名必须是public void bar (Object[] arr),编译器允许您将任何类型的数组传递给该方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多