java - 从 java8 迁移到 java9 时,对方法的引用不明确

标签 java compiler-errors java-8 java-9 functional-interface

我正在将一个项目从 JAVA 8 迁移到 JAVA 9,但我在让代码正常工作时遇到了一些问题。所有在 JAVA 8 中工作,但在 9 中我有以下错误:

Error java: reference to ok is ambiguous
      both method <T>ok(java.util.function.Supplier<T>)  and method ok(web.Procedure) match

这是我调用方法时的代码:

public ResponseEntity<List<MailTemplateDto>> mailTemplateFindAll() {
    return ok(() -> mailTemplateService.findAll());
}

这里是实现:

 public <T> ResponseEntity<T> ok(Supplier<T> action) {
     return this.body(HttpStatus.OK, action);
 }

 public <T> ResponseEntity<T> ok(T body) {
     return this.ok(() -> {
         return body;
     });
 }

 public ResponseEntity<Void> ok(Procedure action) {
     action.invoke();
     return this.status(HttpStatus.OK);
 }

 public ResponseEntity<Void> ok() {
     return this.status(HttpStatus.OK);
 }

过程接口(interface)代码:

@FunctionalInterface
public interface Procedure {
    void invoke();
}

有什么想法吗?


可重现代码::

public class Q48227496 {

    public A<?> test() {
        return ok(() -> System.out.append("aaa"));
    }

    private class A<T> {
    }

    private <T> A<T> ok(java.util.function.Supplier<T> action) {
        return new A<>();
    }

    public <T> A<T> ok(T body) {
        return new A<>();
    }

    private <T> A<T> ok(Procedure action) {
        return new A<>();
    }

    public <T> A<T> ok() {
        return new A<>();
    }

    @FunctionalInterface
    public interface Procedure {
        void invoke();
    }
}

导致以下错误 编译器::

error: reference to ok is ambiguous
        return ok(() -> System.out.append("aaa"));
               ^
  both method <T#1>ok(Supplier<T#1>) in Q48227496 and method <T#2>ok(Procedure) in Q48227496 match
  where T#1,T#2 are type-variables:
    T#1 extends Object declared in method <T#1>ok(Supplier<T#1>)
    T#2 extends Object declared in method <T#2>ok(Procedure)

最佳答案

这是一个错误。

已报告错误 ID:JDK-8195598


我进一步简化了你的例子:

public class Q48227496 {
    public CompletableFuture<?> test() {
        return ok(() -> System.out.append("aaa"));
    }
    public <T> CompletableFuture<T> ok(Supplier<T> action) {
        return CompletableFuture.supplyAsync(action);
    }
    public <T> CompletableFuture<T> ok(T body) {
        return CompletableFuture.completedFuture(body);
    }
    public CompletableFuture<Void> ok(Runnable action) {
        return CompletableFuture.runAsync(action);
    }
}

这在 Java 9 的发布版本中失败,带有“reference to ok is ambiguous” ”,说明“both method <T>ok(Supplier<T>) in Q48227496 and method ok(Runnable) in Q48227496 match ”。

只是改变了方法的顺序

public class Q48227496 {
    public CompletableFuture<?> test() {
        return ok(() -> System.out.append("aaa"));
    }
    public <T> CompletableFuture<T> ok(T body) {
        return CompletableFuture.completedFuture(body);
    }
    public <T> CompletableFuture<T> ok(Supplier<T> action) {
        return CompletableFuture.supplyAsync(action);
    }
    public CompletableFuture<Void> ok(Runnable action) {
        return CompletableFuture.runAsync(action);
    }
}

使编译器无错误地接受代码。

因此,很明显,这是一个编译器错误,因为方法声明的顺序永远不会影响代码的有效性。

此外,删除 ok(T)方法使代码被接受。

请注意,每当编译器接受代码时,它都会考虑 ok(Supplier)ok(Runnable) 更具体,这是匹配两者的函数参数的预期行为。

关于java - 从 java8 迁移到 java9 时,对方法的引用不明确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48227496/

相关文章:

java - 使用java 8流在2个列表中查找元素匹配

java - 单击 JButton 时退出 JFrame

java - 在文本区域中搜索单词

java - 如何仅使用 TestPropertySource 加载数据库一次并在多个测试类中使用它?

java - 阻止用户在文本字段中输入字符,仅允许使用磁条读取器 (MSR) 进行刷卡

java - 通过cmd行编译时出错

c - header .h : No such file or directory even though source and header are in same directory

java - 使用流和 lambda 表达式从文件中提取数字

java编译器奇怪: field declared in same class,但 "not visible"

groovy - 如何使用 play 框架 1.4.2 迭代模板中的 map