gpt4 book ai didi

java - Guava future 中不明确的 lambda 重载

转载 作者:行者123 更新时间:2023-12-02 03:03:19 27 4
gpt4 key购买 nike

我相信我在这里遇到了 eclipse 错误,但我想确认一下。
我使用的是java 8(jdk 1.8.0_102),我的代码编译正常,但eclipse给我一个错误。

我的代码如下所示:

public ListenableFuture<ProtoBufExchange> myMethod(
//some code here
return Futures.transform(future,(Request.Builder reqBuilder) -> {

//some code here

return Futures.immediateFuture(exchange);
}

eclipse中显示的错误是这样的:

The method transform(ListenableFuture<Request.Builder>, AsyncFunction<? super Request.Builder,? extends ProtoBufExchange>) is ambiguous for the type Futures.

如果我进行强制转换,Eclipse 不会提示:

public ListenableFuture<ProtoBufExchange> myMethod(
//some code here
return Futures.transform(future,(AsyncFunction<Request.Builder, ProtoBufExchange>) (Request.Builder reqBuilder) -> {

//some code here

return Futures.immediateFuture(exchange);
}

我知道 guava 15.0 Future.transform() 已重载,具有以下两种形式(在较新的 guava 版本上,异步方法具有不同的名称):

transform(ListenableFuture<I> input, Function<? super I,? extends O> function)

transform(ListenableFuture<I> input, AsyncFunction<? super I,? extends O> function)

但是jdk编译器以某种方式解决了这个歧义。也许是因为在上面的代码中,如果我们实现的是 Function,而不是 AsyncFunction,Futures.transform 的返回类型将与方法返回类型不匹配。

这是 eclipse 上的错误吗?我在这里错过了什么吗?

有关我的环境的更多详细信息:

jdk:1.8.0_102
eclipse :4.6.2
Guava :15.0

最佳答案

“显式类型 lambda 表达式”和“隐式类型 lambda 表达式”之间存在区别。

形式为 name -> expressiorOrBlock 的隐式类型 lambda 表达式或(name[,name]*) -> expressionOrBlock需要其上下文(即已解析的方法)来确定其类型,因此不用于消除重载方法的歧义。这样做并非不可能,但由于由此产生的复杂性,规范明确排除了这一点。

格式为 (Type name[, Type name]*) -> expressionOrBlock 的显式类型 lambda 表达式拥有确定其功能签名所需的一切,包括其返回类型,这允许使用它们来消除重载方法的歧义。

提供一个简单的例子:

interface F<T,R> {
R apply(T t);
}
interface AF<T,R> {
Future<R> apply(T t);
}
static <T,R> Future<R> method(F<T,R> f) {
return null;
}
static <T,R> Future<R> method(AF<T,R> f) {
return null;
}
public static void main(String[] args) {
// these two don't compile
method(x -> "bla");
method(x -> new FutureTask<String>(null));

// these two do compile
method((Object x) -> "bla");
method((Object x) -> new FutureTask<String>(null));
}

正式规则在JLS, §15.12.2.5. Choosing the Most Specific Method中指定。 ,但它还包含一个非正式的提示:

The informal intuition is that one method is more specific than another if any invocation handled by the first method could be passed on to the other one without a compile-time error.

我想,很容易看出method(AF)可以处理的每个调用也可以通过 method(F) 处理,而相反的情况不适用,即 method((Object x) -> "bla")调用只能由 method(F) 处理,所以它没有歧义,而method((Object x) -> new FutureTask<String>(null))两者都可以处理,但是 method(AF) 更具体

relevant formal part是:

A functional interface type S is more specific than a functional interface type T for an expression e if T is not a subtype of S and one of the following is true (where U₁ ... U<sub>k</sub> and R₁ are the parameter types and return type of the function type of the capture of S, and V₁ ... V<sub>k</sub> and R₂ are the parameter types and return type of the function type of T):

  • If e is an explicitly typed lambda expression (§15.27.1), then one of the following is true:
    • R₂ is void.
    • R₁ <: R₂.

因此,在涉及显式类型化 lambda 表达式的特定情况下,函数类型的返回类型已经足以消除歧义。

但请注意,编译示例代码也会产生警告:

warning: [overloads] <T#1,R#1>method(F<T#1,R#1>) … is potentially ambiguous with <T#2,R#2>method(AF<T#2,R#2>)

提醒一下,隐式类型的 lambda 表达式对于此类重载方法总是不明确的,而且使用显式类型 lambda 表达式的方法选择可能并不直观。

关于java - Guava future 中不明确的 lambda 重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42142255/

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