【问题标题】:Two methods for creating generic arrays with the same result, but only one works创建具有相同结果的通用数组的两种方法,但只有一种有效
【发布时间】:2018-06-10 14:21:27
【问题描述】:

我最近尝试创建一个泛型数组,发现不允许这样做:
Cannot create generic array of OptionSet<T>

我决定做一个测试类,发现有一个不同的方法,结果完全相同:

public class Test {

    @SuppressWarnings("unchecked")
    public static final void main(String[] args) {
        A<String> a = null;
        A<String> b = null;

        A<?>[] array1 = array(a, b); // fine, only a warning
        A<?>[] array2 = new A<String>[] {a, b}; // Error: Cannot create a generic array of Test.A<String>
    }

    @SuppressWarnings("unchecked")
    private static final <T> A<T>[] array(A<T>... a) {
        return a; // fine, only a warning
    }

    private static final class A<T> {}

}

这是为什么呢?这两种方法的结果完全相同,但由于某种原因,一种会引发错误,另一种则可以正常工作,尽管它会发出警告。

【问题讨论】:

  • 这是由于type erasure。核心点:泛型类型只存在于编译时。它们在运行时被替换为其上限。要了解如何在标准 API 中处理此类内容,您可以查看 ArrayList 的实现。它使用Object[] elementData。当返回 E 类型的元素时(例如,ArrayList#get(int index)),它们被显式转换(并且警告通过 @SuppressWarnings("unchecked") 被抑制。

标签: java arrays generics


【解决方案1】:

这是因为在通过返回类型 private static final &lt;T&gt; A&lt;T&gt;[] array(A&lt;T&gt;... a) 调用方法的情况下会发生强制转换,而不是在您直接创建实例的 A&lt;?&gt;[] array2 = new A&lt;String&gt;[] {a, b}; 的情况下。

要让它工作你需要像下面这样显式地转换:

A<?>[] array2 = (A<String>[])(new A<?>[] { a, b });

发生的事情是元素是A&lt;String&gt;,而不是数组本身;它仍然是通用的 A&lt;?&gt; 直到你明确地转换它。

【讨论】:

  • 仍然,为什么我需要显式转换它?我希望它是A&lt;String&gt;[],只要我只将A&lt;String&gt; 元素传递给它,而当我不传递错误时会抛出错误。
  • 另外,我注意到当我有一个方法 final &lt;T&gt; A&lt;T&gt;[] array(A&lt;T&gt; a, A&lt;T&gt; b) 时它不起作用,因为我无法将 A&lt;?&gt;[] 转换为 A&lt;T&gt;[]。我该如何解决?
  • @Priv 不,这不是这里的原因。您将返回单个对象而不是对象数组A&lt;T&gt;[]。在这里你需要做类似的事情,即return (A&lt;T&gt;[])(new A&lt;?&gt;[]{a,b})return (A&lt;T&gt;[])(new A[]{a,b});
猜你喜欢
  • 2015-05-01
  • 2020-04-18
  • 2013-05-01
  • 2019-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-23
相关资源
最近更新 更多