【问题标题】:Cannot compile method reference in JDK 11无法在 JDK 11 中编译方法引用
【发布时间】:2019-08-13 10:32:33
【问题描述】:

我目前正在将一个项目迁移到 JDK 11 并使用 Maven 对其进行编译。但是,Maven 在单个方法引用上抛出了一个不稳定的问题(它在其他地方没有问题)。有问题的方法如下所示:

public class MyThing {

    boolean something = true;

    // ...

    public boolean isSomething() {
        return something;
    }

    // ...
}

对上述方法的调用看起来或多或少是这样的:

return methodThatGetsOptionalDefinition(aString)                 // Optional<Definition>
        .map(definition -> defenition.getMyThing(anotherString)) // Optional<MyThing>
        .map(MyThing::isSomething)                               // Optional<Boolean>
        .orElse(true);

编译这个,Maven 抛出以下消息:

> mvn clean install -Pdist-snapshot -DskipTests
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project XXXXX: Compilation failure
[ERROR] /D:/XXXXX.java:[63,38] incompatible types: invalid method reference
[ERROR]     method isSomething in class XXXXX.MyThing cannot be applied to given types
[ERROR]       required: no arguments
[ERROR]       found: java.lang.Object
[ERROR]       reason: actual and formal argument lists differ in length
[ERROR]
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.

如果我像这样扩展方法引用,它编译没有问题:

return methodThatGetsOptionalDefinition(aString)
        .map(definition -> defenition.getMyThing(anotherString))
        .map(myThing -> myThing.isSomething())
        .orElse(true);

键入 Optional 也可以:

return methodThatGetsOptionalDefinition(aString)
        .<MyThing>map(definition -> defenition.getMyThing(anotherString))
        .map(myThing -> myThing.isSomething())
        .orElse(true);

在 Open JDK 版本 11.0.1 和 11.0.2 中使用 IntelliJ 编译项目时会出现同样的错误。具有讽刺意味的是,IntelliJ 抱怨“Lambda 可以替换为方法引用”。使用不同的“语言模式”时也会出现此问题。

<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <source>11</source>
        <target>11</target>
    </configuration>
</plugin>

有人知道为什么会发生这种情况吗?

一些具体的实现细节已经被混淆了。

【问题讨论】:

  • 我无法复制。通过对somethingthingyService.getMyThingname 和封闭方法的返回类型的正确假设,您的代码可以在我的 JDK 11 上正常编译。A Minimal, Complete, and Verifiable example,好吗?
  • 只是随机拍摄:Optional.&lt;MyThing&gt;ofNullable(thingyService.getMyThing(name)) 可能是另一种可能的解决方法。
  • 一个最小的例子很遗憾是不可能的。如前所述,方法参考适用于其他几个地方(包括简单的 JUnit 测试)。它可以在 JDK 8 上完美编译。但是,我编辑了这篇文章以减少假设并更明确地说明导致问题的代码。我会看看显式输入是否能解决问题。
  • 有趣地键入“解决”了编译时的问题。但是 IntelliJ 仍然认为可以推断出显式类型参数(他们可以)。这听起来像是 JDK 的问题。
  • 如果您遇到同样的问题,请点赞。有些人显然不喜欢问题的“不易重现”的性质;-)

标签: java maven lambda compiler-errors java-11


【解决方案1】:

这与map方法的Type定义有关。

为了提供方法引用,方法必须具有匹配的类型定义。流图有一个函数方法,但你的是一个生产者函数。

Function = (T) -> R
Producer = () -> R

所以,Method::isSomething() 与 Stream.map 不兼容,但您的内联闭包 myThing -&gt; myThing.isSomething() 是..

【讨论】:

  • 恐怕这是错误的。对于功能接口,() -&gt; R 可以解释为 (this) -&gt; R。上面的例子:如果链被键入,它会再次工作。它还在 JDK 8 中编译,没有问题,并且可以在一个最小的示例中工作。
猜你喜欢
  • 2019-03-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-23
  • 1970-01-01
相关资源
最近更新 更多