当前位置: 首页 > 知识库问答 >
问题:

Eclipse对函数的“提取到方法”导致编译错误

夏弘文
2023-03-14

从一个包含两个字段的类开始,一个是构造函数和getters,一个是name,一个是id,我编写了这个测试,它运行绿色:

@Test
public void test() {
    List<A> list = Arrays.asList(new A(null, "a"), new A(null, "b"));

    Collections.sort(list,
            Comparator
            .comparing(A::getName, Comparator.nullsLast(Comparator.naturalOrder()))
            .thenComparing(A::getId, Comparator.nullsLast(Comparator.reverseOrder())));

    assertThat(list.get(0).id, is("b"));
}

但是,如果我在A::getName上选择Eclipse的快速修复“提取到方法”:

我在下一行突然发现了两个编译错误(<代码>然后比较(…) ):

@Test
public void test() {
    List<A> list = Arrays.asList(new A(null, "a"), new A(null, "b"));

    Collections.sort(list,
            Comparator
            .comparing(extracted(), Comparator.nullsLast(Comparator.naturalOrder()))
            .thenComparing(A::getId, Comparator.nullsLast(Comparator.reverseOrder())));

    assertThat(list.get(0).id, is("b"));
}

private Function<? super A, ? extends String> extracted() {
    return A::getName;
}

说:

型式试验。A没有定义适用于此处的getId(capture#1-of?super Test.A)

然后比较的方法(函数

为什么这会导致错误?我做错了什么?

共有1个答案

危飞跃
2023-03-14

这要归咎于重构。它创建了两个需要在类型推断之前/期间捕获的新通配符。在此之后,类型不再统一,推理也无法找到解决方案。

另一个bug是javac 8接受了这段代码,但这在javac 9中已得到修复(我尝试构建9-ea 118)。

在该版本中,javac的错误消息如下:

error: no suitable method found for thenComparing(A::getId,Comparator<T#1>)
          .thenComparing(A::getId, Comparator.nullsLast(Comparator.reverseOrder())));
          ^
method Comparator.<U#1>thenComparing(Function<? super CAP#1,? extends U#1>,Comparator<? super U#1>) is not applicable
  (cannot infer type-variable(s) U#1
    (argument mismatch; invalid method reference
      method getId in class A cannot be applied to given types
        required: no arguments
        found: CAP#1
        reason: actual and formal argument lists differ in length))
method Comparator.<U#2>thenComparing(Function<? super CAP#1,? extends U#2>) is not applicable
  (cannot infer type-variable(s) U#2
    (actual and formal argument lists differ in length))
where T#1,T#2,U#1,T#3,U#2 are type-variables:
    T#1 extends T#2
    T#2 extends Comparable<? super T#2>
    U#1 extends Object declared in method <U#1>thenComparing(Function<? super T#3,? extends U#1>,Comparator<? super U#1>)
    T#3 extends Object declared in interface Comparator
    U#2 extends Comparable<? super U#2> declared in method <U#2>thenComparing(Function<? super T#3,? extends U#2>)
where CAP#1 is a fresh type-variable:
    CAP#1 extends Object super: A from capture of ? super A
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output

编辑:javac中的bug很可能是https://bugs.openjdk.java.net/browse/JDK-8039214第9版确实解决了这一问题。这被称为处理javac无法正确处理通配符捕获的相关bug集群的“主bug”。在该bug中,建议发布说明使用以下文本:

javac编译器在处理通配符和“捕获”类型变量时的行为已得到改进,以符合语言规范。这改进了某些异常情况下的类型检查行为。这也是一个源代码不兼容的变化:由于程序依赖javac错误,以前编译过的通配符的某些用法可能无法编译。

<罢工> 我相信在这两种情况下(javac 9和ecj),关于 getId是次要的,推理的结果已经失败。

仔细看一下,getId错误是导致类型检查失败的主要原因:

  • 比较(..)的解析类型 is<代码>比较器

这与JDK-8039214中的描述大致相符,即javac 8错误地使用了捕获的界限,而不是捕获本身。我含糊地说,因为错误谈到了上界,而这里javac 8似乎甚至使用了下界。

 类似资料:
  • 问题内容: 对于这两个进口; 我收到此错误: 如何解决此错误? 问题答案: 该错误是由您的Eclipse配置引起的。您可以将其减少为警告。更好的是,使用不属于非公共API的Base64编码器。Apache Commons有一个,或者当您已经使用Java 1.8时,请使用。

  • 我有osgi项目。每个包都是一个单独的maven项目。项目足够大,包括大约10个包。一切正常,一切正常。 在org.apache.maven.plugin.abstractCompilerMojo.execute(abstractCompilerMojo.java:656)在org.apache.maven.plugin.compilerMojo.execute(compilerMojo.java

  • 我在编译顺序时遇到编译器错误。java文件,即使它包含另一个打包类的导入语句。我不完全确定为什么会发生这种情况,但这是一个目录树,其中包含一些文件: > com/my/domain/Order.java 这个文件里面有下面的包和导入: com/my/utils/MyDate。此文件中包含以下包和导入: 编译顺序时出现编译器错误。java: 我仍然不知道如何解决这个问题后,试图从评论。这里有一些更多

  • 问题内容: 遇到一个错误地使用 而不是 在其代码中的人,它没有显示为编译错误。 是因为 是相同的 ? 问题答案: 没有编译错误,因为它是有效的(尽管相当无用) 一元运算符 ,其使用方式与以下方式相同: Java语言规范中的相关部分是Unary Plus运算符+(第15.15.3节) 。它指定调用一元运算会导致操作数的一元数值提升(第5.6.1节)。这意味着: * 如果操作数是编译时类型的,,,或,

  • 我使用的是Windows7 32位机器。已安装节点12 v12。22.1,npm 6.14。12 创建了“npx创建反应应用程序反应” 导致打开web浏览器并显示此消息。 请帮助我解决问题并运行应用程序。

  • 尝试与JIB(容器化您的GradleJava项目)与我的Java项目集成。 在此留档之后:https://github.com/GoogleContainerTools/jib/tree/master/jib-gradle-plugin 在我的项目中添加了以下内容: Gradle版本是:5.6.4 使用“/gradlew”构建的编译工作正常。但是,当执行“gradle jib”时,会出现以下错误: