奇怪的汇编问题
以下类将不会编译:
public class Thing {
public static <T> T foo(java.util.function.Supplier<T> supplier) {
return supplier.get();
}
public static <T> T bar(java.util.function.Function<Integer, T> function) {
return function.apply(42);
}
public static void main(String... args) {
System.out.println(foo(() -> "hello")); // 1
System.out.println(bar(any -> "hello")); // 2 !!!
System.out.println(bar((Integer any) -> "hello")); // 3
System.out.println(Thing.<String>bar(any -> "hello")); // 4
println(bar(any -> "hello")); // 5
}
private static void println(String string) {
System.out.println(string);
}
}
该问题在main()
方法(所有其他行都很好)中在线[2]:
[ERROR] .../Thing.java:[13,19] reference to println is ambiguous
both method println(char[]) in java.io.PrintStream and method println(java.lang.String) in java.io.PrintStream match
[ERROR] .../Thing.java:[13,31] incompatible types: inference variable T has incompatible bounds
lower bounds: char[],java.lang.Object
lower bounds: java.lang.String
我不明白为什么编译器认为在bar()的返回类型
(char []
或字符串
),无法决定println()
println()< /代码>应使用方法。在行[1]上,可以推断出
foo()
的返回类型是string
和在线[3],我不明白如何指定如何指定类型任何
(Integer
)会有所帮助,因为它不能让其他任何东西给定bar()
方法的签名。
The following class will not compile:
public class Thing {
public static <T> T foo(java.util.function.Supplier<T> supplier) {
return supplier.get();
}
public static <T> T bar(java.util.function.Function<Integer, T> function) {
return function.apply(42);
}
public static void main(String... args) {
System.out.println(foo(() -> "hello")); // 1
System.out.println(bar(any -> "hello")); // 2 !!!
System.out.println(bar((Integer any) -> "hello")); // 3
System.out.println(Thing.<String>bar(any -> "hello")); // 4
println(bar(any -> "hello")); // 5
}
private static void println(String string) {
System.out.println(string);
}
}
The issue is on line [2] in the main()
method (all other lines are fine):
[ERROR] .../Thing.java:[13,19] reference to println is ambiguous
both method println(char[]) in java.io.PrintStream and method println(java.lang.String) in java.io.PrintStream match
[ERROR] .../Thing.java:[13,31] incompatible types: inference variable T has incompatible bounds
lower bounds: char[],java.lang.Object
lower bounds: java.lang.String
I don't understand why the compiler thinks there is an ambiguity on the return type of bar()
(char[]
or String
) and can't decide which flavor of println()
method should be used. On line [1], it can infer that the return type of foo()
is String
and on line [3], I don't understand how specifying the type of any
(Integer
) helps because it could not be anything else given the signature of the bar()
method.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是因为隐式键入的lambda
任何 - &gt; “你好”
不是与适用性相关,因此在确定哪种类型的callbar(任何 - &gt;“ hello”)
时,实际上被忽略://docs.oracle.com/javase/specs/jls/se17/html/jls-18.html#jls-18.5.2.1“ rel =“ nofollow noreferrer”> nofollow noreferrer“> invocation类型type type type penperion ,为了选择正确的println
调用。可以从第一个链接中找到理由:
因此,除了我们将其传递到
system.out.println
的事实外,bar
的返回类型几乎没有界限类型。编译器试图推断我们正在尝试使用上面第二个链接中的规则来调用哪个过载,但是println(string)
和println(char [])
都看起来像有效的超载!其他行工作的原因是:
system.out.println(foo(() - &gt;“ hello”));
system.out.println(bar(((integer noy any) - &gt;“ hello” hello'' );
这些lambdas都与适用性有关,因为它们是明确键入lambdas (尽管该规则有一些例外)。请注意,没有参数的lambda被视为明确键入的lambda。
system.out.println(物质
由于您提供了
bar
的类型参数,因此编译器无需使用类型推荐来确定它。现在可以琐碎地确定bar
返回字符串
,因此您必须调用println(string)
。。
println(bar(Any -&gt;“ Hello”));
只有一个
println
的过载,即使我们不知道bar
返回string
我们仍然可以看到bar
调用将传递给println(string)
。。
我建议您查看与适用性无关的表达式列表,并与之相处:)
This is because the implicitly typed lambda
any -> "hello"
is not pertinent to applicability, and so it is practically ignored when determining what type the callbar(any -> "hello")
should be (See Invocation Type Inference sections of the JLS), in order to select the correctprintln
call.The justification can be found from the first link:
So other than the fact that we are passing it to
System.out.println
, there are practically no bounds on the return type ofbar
at all - it could be any reference type. The compiler tries to infer which overload we are trying to call using the rules in that second link above, butprintln(String)
andprintln(char[])
both seem like valid overloads!The reasons why the other lines work are:
System.out.println(foo(() -> "hello"));
System.out.println(bar((Integer any) -> "hello"));
these lambdas are all pertinent to applicability, because they are explicitly typed lambdas (though this rule has some exceptions). Note that a lambda with no parameters counts as an explicitly typed lambda.
System.out.println(Thing.<String>bar(any -> "hello"));
Since you have provided the type parameter of
bar
, the compiler does not need to determine it using type inference. It can now be trivially determined thatbar
returnsString
, so you must be callingprintln(String)
.println(bar(any -> "hello"));
There is only one overload of
println
to pick, so even though we can't know thatbar
returnsString
from the lambda, we can still do it by seeing that thebar
call is being passed toprintln(String)
.I recommend that you have a look at the list of expressions that are not pertinent to applicability and play around with them :)