gpt4 book ai didi

java - 构造函数引用 - 创建泛型数组时没有警告

转载 作者:IT老高 更新时间:2023-10-28 20:25:34 26 4
gpt4 key购买 nike

在 Java 中,不能直接创建泛型类型的数组:

Test<String>[] t1 = new Test<String>[10]; // Compile-time error

但是,我们可以使用原始类型来做到这一点:

Test<String>[] t2 = new Test[10]; // Compile warning "unchecked"

在 Java 8 中,还可以使用构造函数引用:

interface ArrayCreator<T> {
T create(int n);
}

ArrayCreator<Test<String>[]> ac = Test[]::new; // No warning
Test<String>[] t3 = ac.create(10);

为什么编译器在最后一种情况下不显示警告?它仍然使用原始类型来创建数组,对吧?

最佳答案

你的问题是有道理的。简而言之,方法引用确实使用了原始类型(或应该使用原始类型),并且禁止创建泛型数组的原因在使用方法引用时仍然适用,因此,能够静默创建函数创建泛型数组显然违反了语言设计的意图。

之所以禁止创建泛型数组,是因为源于前泛型时代的数组类型继承与泛型类型系统不兼容。 IE。你可以写:

IntFunction<List<String>[]> af = List[]::new; // should generate warning
List<String>[] array = af.apply(10);
Object[] objArray = array;
objArray[0] = Arrays.asList(42);
List<String> list = array[0]; // heap pollution

这里必须强调的是,与这里的一些答案相反,编译器确实对表达式List[]::new进行类型推断。推断通用元素类型List<String> .很容易证明仍然禁止创建泛型数组:

IntFunction<List<String>[]> af = List<String>[]::new; // does not compile

自从 List<String>[]::new是非法的,如果List[]::new会很奇怪通过推断它实际上是非法的 List<String>[]::new 被接受而没有警告.

JLS §15.13明确指出:

If a method reference expression has the form ArrayType :: new, then ArrayType must denote a type that is reifiable (§4.7), or a compile-time error occurs.

这已经暗示 List<String>[]::new是非法的,因为 List<String>是不可具体化的,而 List<?>[]::new是合法的,如 List<?>是可具体化的,List[]::new如果我们考虑 List 是合法的作为原始类型,作为原始类型 List是可具体化的。

然后 §15.13.1 规定:

If the method reference expression has the form ArrayType :: new, a single notional method is considered. The method has a single parameter of type int, returns the ArrayType, and has no throws clause. If n = 1, this is the only potentially applicable method; otherwise, there are no potentially applicable methods.

换句话说,List[]::new 的行为上面的表达式和你写的一样:

    IntFunction<List<String>[]> af = MyClass::create;

private static List[] create(int i) {
return new List[i];
}

除了方法create只是名义上的。事实上,通过这个显式方法声明,create 处只有 原始类型 警告。方法,但没有关于 List[] 转换的未选中警告至List<String>[]在方法引用。所以可以理解,List[]::new 中的编译器会发生什么?这种情况下,使用原始类型的方法只是名义上的,即源代码中不存在。

但是没有unchecked警告明显违反了JLS §5.1.9, Unchecked Conversion :

Let G name a generic type declaration with n type parameters.

There is an unchecked conversion from the raw class or interface type (§4.8) G to any parameterized type of the form G<T₁,...,Tₙ>.

There is an unchecked conversion from the raw array type G[]ᵏ to any array type of the form G<T₁,...,Tₙ>[]ᵏ. (The notation []ᵏ indicates an array type of k dimensions.)

Use of an unchecked conversion causes a compile-time unchecked warning unless all type arguments Tᵢ (1 ≤ in) are unbounded wildcards (§4.5.1), or the unchecked warning is suppressed by the SuppressWarnings annotation (§9.6.4.5).

所以,List[] 的转换至List<?>[]是合法的,如 List使用无界通配符参数化,但从 List[] 转换至List<String>[]必须产生 unchecked 警告,这在此处至关重要,因为使用 List[]::new不会产生与显式创建方法一起出现的 raw type 警告。 raw type 警告的缺失似乎不是违规行为(据我了解 §4.8 ),如果 javac 不会有问题创建了所需的未选中警告。

关于java - 构造函数引用 - 创建泛型数组时没有警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42346895/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com