下界通配符在javac中造成麻烦,但不是Eclipse [英] Lower-bounded wild card causes trouble in javac, but not Eclipse
问题描述
这段代码在Eclipse中编译,但不在javac中:
$ b
import java.util .function.Consumer;
public class Test {
public static final void m1(Consumer<?> c){
m2(c);
}
private static final< T> void m2(Consumer <?super T> c){
}
}
javac输出:
$ b
C:\Users\lukas\workspace> javac -version
javac 1.8.0_92
C:\Users\lukas\workspace> javac Test.java
Test.java:5:error:method m2 in class Test can not适用于给定的类型;
m2(c);
^
要求:消费者< ;?超T>
找到:消费者< CAP#1>
reason:无法推断类型变量T
(参数不匹配; Consumer< CAP#1>无法转换为Consumer< ;? super T>)
其中T是类型 - 变量:
T extends在方法< T> m2(Consumer< ;? super T>)
中声明的对象,其中CAP#1是一个新的类型变量:
CAP#1 extends Object捕获?
1错误
---------------------------------------- ------------------------
哪个编译器错了,为什么? ( Eclipse错误报告和这里讨论的部分)
此代码与JLS 8是合法的。javac版本8及更早版本在处理通配符和捕获方面存在一些错误。从版本9开始(早期访问,我尝试了版本ea-113和更新版本),并且javac接受此代码。
为了理解编译器如何根据JLS分析它,对于区分通配符捕获,类型变量,推理变量等是至关重要的。类型 c
是 Consumer< capture#1-of?>
(javac会写 Consumer< CAP#1>
)。这种类型是未知的,但是是固定的。
类型推断包括确定 ⟨c→消费者<?超级T#0>⟩ 这是逐步减少的(通过应用 JLS 18.2 ): ⟨消费者<俘获#1→?→消费者< ;? super T#0>⟩ ⟨捕获#1个? < =? super T#0⟩ ⟨T#0 <:捕获#1-⟩ T #0 <:捕获#1 最后一行是类型绑定并且完成了缩减。由于没有进一步的约束,解决方法将 通过这些步骤,类型推断已经证明 直观上,所示解决方案告诉我们:如果 This piece of code compiles in Eclipse but not in javac: javac output: Which compiler is wrong and why? (Eclipse bug report and parts of discussion here) This code is legal wrt JLS 8. javac version 8 and earlier had several bugs in how they handle wildcards and captures. Starting with version 9 (early access, I tried version ea-113 and newer) also javac accepts this code. To understand how a compiler analyzes this according to JLS, it is essential to tell apart what are wildcard captures, type variables, inference variables and such. The type of The parameter of During type inference an inference variable, denoted by ecj as Type inference consists in determining, whether ⟨c → Consumer<? super T#0>⟩ Which is stepwise reduced (by applying JLS 18.2): ⟨Consumer<capture#1-of ?> → Consumer<? super T#0>⟩ ⟨capture#1-of ? <= ? super T#0⟩ ⟨T#0 <: capture#1-of ?⟩ T#0 <: capture#1-of ? The last line is a "type bound" and reduction is done. Since no further constraints are involved, resolution trivially instantiates By these steps, type inference has proven that Intuitively, the shown solution tells us: whatever type the capture may represent, if 这篇关于下界通配符在javac中造成麻烦,但不是Eclipse的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! Consumer< ?超级T>
,其中 T
是一个要通过类型推断实例化的类型变量。
<在类型推断过程中,一个用ecj表示的推断变量 T code>。
T#0
是否可以实例化为任何类型而不违反任何给定的类型约束。在这个特殊情况下,我们从这个约束开始:
T#0
实例化为类型 capture#1-of
。
m2
适用于这个特定的调用。 qed。
T
设置为捕获可能表示的任何类型表示完全相同的类型,没有违反类型约束。这是可能的,因为捕获在开始类型推断之前是固定的。import java.util.function.Consumer;
public class Test {
public static final void m1(Consumer<?> c) {
m2(c);
}
private static final <T> void m2(Consumer<? super T> c) {
}
}
C:\Users\lukas\workspace>javac -version
javac 1.8.0_92
C:\Users\lukas\workspace>javac Test.java
Test.java:5: error: method m2 in class Test cannot be applied to given types;
m2(c);
^
required: Consumer<? super T>
found: Consumer<CAP#1>
reason: cannot infer type-variable(s) T
(argument mismatch; Consumer<CAP#1> cannot be converted to Consumer<? super T>)
where T is a type-variable:
T extends Object declared in method <T>m2(Consumer<? super T>)
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ?
1 error
----------------------------------------------------------------
c
is Consumer<capture#1-of ?>
(javac would write Consumer<CAP#1>
). This type is unknown, but fixed.m2
has type Consumer<? super T>
, where T
is a type variable to be instantiated by type inference.T#0
, is used to represent T
. T#0
can be instantiated to any type without violating any given type constraints. In this particular case we start with this contraint:
T#0
to the type capture#1-of ?
.m2
is applicable for this particular invocation. qed.T
is set to represent the exact same type, no type constraints are violated. This is possible, because the capture is fixed before starting type inference.