gpt4 book ai didi

java - Lambda表达式和方法重载疑惑

转载 作者:太空宇宙 更新时间:2023-11-04 14:31:25 26 4
gpt4 key购买 nike

好的,所以方法重载是一件坏事™。现在这个问题已经解决了,让我们假设我实际上想要重载这样的方法:

static void run(Consumer<Integer> consumer) {
System.out.println("consumer");
}

static void run(Function<Integer, Integer> function) {
System.out.println("function");
}

在 Java 7 中,我可以使用明确的匿名类作为参数轻松调用它们:

run(new Consumer<Integer>() {
public void accept(Integer integer) {}
});

run(new Function<Integer, Integer>() {
public Integer apply(Integer o) { return 1; }
});

现在在 Java 8 中,我当然想用 lambda 表达式调用这些方法,而且我可以!

// Consumer
run((Integer i) -> {});

// Function
run((Integer i) -> 1);

既然编译器应该能够推断Integer,那么为什么我不离开Integer呢?

// Consumer
run(i -> {});

// Function
run(i -> 1);

但这不能编译。编译器(javac、jdk1.8.0_05)不喜欢这样:

Test.java:63: error: reference to run is ambiguous
run(i -> {});
^
both method run(Consumer<Integer>) in Test and
method run(Function<Integer,Integer>) in Test match

对我来说,直觉上,这没有意义。产生返回值(“值兼容”)的 lambda 表达式与产生 void(“void 兼容”)的 lambda 表达式之间绝对没有歧义,如 JLS §15.27 中所述。

但是,当然,JLS 是深刻而复杂的,我们继承了 20 年的向后兼容性历史,并且还有一些新的东西,例如:

Certain argument expressions that contain implicitly typed lambda expressions (§15.27.1) or inexact method references (§15.13.1) are ignored by the applicability tests, because their meaning cannot be determined until a target type is selected.

from JLS §15.12.2

上述限制可能与 JEP 101 没有完全实现有关,如 herehere 所示。

问题:

谁能准确地告诉我 JLS 的哪些部分指定了这种编译时歧义(或者是编译器错误)?

奖励:为什么事情会这样决定?

更新:

使用jdk1.8.0_40,上面的编译和工作正常

最佳答案

我想你找到了this bug in the compiler: JDK-8029718 (or this similar one in Eclipse: 434642)。

JLS §15.12.2.1. Identify Potentially Applicable Methods相比:

  • A lambda expression (§15.27) is potentially compatible with a functional interface type (§9.8) if all of the following are true:

    • The arity of the target type's function type is the same as the arity of the lambda expression.

    • If the target type's function type has a void return, then the lambda body is either a statement expression (§14.8) or a void-compatible block (§15.27.2).

    • If the target type's function type has a (non-void) return type, then the lambda body is either an expression or a value-compatible block (§15.27.2).

请注意“void兼容 block ”和“值兼容 block ”之间的明显区别。虽然在某些情况下 block 可能两者兼而有之,但 §15.27.2. Lambda Body 部分明确指出像 () -> {} 这样的表达式是“void 兼容 block ”,因为它正常完成而不返回值。显然,i -> {} 也是一个“void 兼容 block ”。

根据上面引用的部分,lambda 与值不兼容的 block 以及具有(非void)返回类型的目标类型的组合不是潜在的候选者方法重载决策。所以你的直觉是对的,这里不应该有任何歧义。

不明确 block 的示例是

() -> { throw new RuntimeException(); }
() -> { while (true); }

因为它们没有正常完成,但您的问题并非如此。

关于java - Lambda表达式和方法重载疑惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26091682/

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