【问题标题】:Java Generic Arrays : Why does this compile and what does this mean? [duplicate]Java Generic Arrays:为什么会编译,这是什么意思? [复制]
【发布时间】:2019-08-12 04:29:33
【问题描述】:

Java 不允许直接创建泛型数组。我知道由于擦除泛型类型在运行时未知,而数组需要在运行时进行类型检查,因此两者不兼容。

这段代码无法编译-

Holder<Integer>[] integers = new Holder<Integer>[5];

很好,但我不确定为什么这段代码实际上可以编译(带有不安全类型转换的警告)?

Holder<Integer>[] holders = new Holder[5];
holders[0] = new Holder<Integer>(5);
holders[1] = new Holder<Integer>(5);
holders[2] = new Holder<Integer>(5);

我不完全明白我实际上是通过删除菱形括号来欺骗编译器的。创建泛型数组是否可以接受?

此外,当我将此行添加到代码中时 - holders[3] = new Holder&lt;String&gt;("Hello"); 它会引发编译错误Holder&lt;String&gt; can not be converted to Holder&lt;Integer&gt; 我觉得这很奇怪,因为据我所知,不允许泛型数组的整个想法是因为数组由于类型擦除而无法区分两种不同的泛型类型。但在这个例子中,编译器可以检测到不正确的类型转换。

我在这里错过了什么?

【问题讨论】:

  • 关键是你可以写((Holder[]) holders)[0] = new Holder&lt;String&gt;(""),这不会失败(这里:当你试图从holders[0]中取出Integer时它会失败)。

标签: java arrays generics


【解决方案1】:

this page,您可以确切地看到为什么不允许创建泛型类型的数组:

Object[] stringLists = new List<String>[];  // compiler error, but pretend it's allowed
stringLists[0] = new ArrayList<String>();   // OK
stringLists[1] = new ArrayList<Integer>();  // An ArrayStoreException should be thrown,
                                            // but the runtime can't detect it.

stringLists 应该只能存储List&lt;String&gt;,但是通过使用上面的代码,我不仅可以欺骗编译器,还可以欺骗运行时允许我存储@由于类型擦除,987654326@ 变为 stringLists

但我不确定为什么这段代码实际上可以编译

好吧,因为Holder 是一个原始类型。见What is a raw type and why shouldn't we use it?。就编译器和运行时而言,创建一个原始类型的数组是完全没问题的,因为在这里你不是说“这个数组只能存储Holder&lt;Integer&gt;”,你只是说“这个数组只能存储Holder(任何东西)”。

创建泛型数组是否可以接受?

嗯,您的数组在技术上不是通用的。我可以将它分配给Holder[] 并将Holder&lt;Foo&gt; 分配给它的一个元素,并且不会发生异常或编译器错误。就编译器而言,这是“可以接受的”,但是因为你失去了类型安全,我不建议你使用它。你应该改用ArrayList&lt;Holder&lt;Integer&gt;&gt; 之类的东西。

我觉得这很奇怪,因为据我了解,不允许泛型数组的整个想法是因为类型擦除,数组无法区分两种不同的泛型类型。但在这个例子中,编译器可以检测到不正确的类型转换。

编译器能检测到不是因为数组不允许你放入Holder&lt;String&gt;,而是因为变量的编译时间类型是Holder&lt;Integer&gt;[]。编译器仍然可以通过查看编译时类型来检查类型,但是一旦您丢失了编译时类型(将其分配给Object[]Holder[] 类型的变量),它就无法做到你。无论如何,数组本身允许任何类型的Holder,因为它是Holder[]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-13
    • 2015-03-12
    相关资源
    最近更新 更多