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

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

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

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

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

这是实施:

  public  ResponseEntity ok(Supplier action) { return this.body(HttpStatus.OK, action); } public  ResponseEntity ok(T body) { return this.ok(() -> { return body; }); } public ResponseEntity ok(Procedure action) { action.invoke(); return this.status(HttpStatus.OK); } public ResponseEntity ok() { return this.status(HttpStatus.OK); } 

Procedure接口的代码:

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

有任何想法吗?


可重现的代码 ::

 public class Q48227496 { public A test() { return ok(() -> System.out.append("aaa")); } private class A { } private  A ok(java.util.function.Supplier action) { return new A(); } public  A ok(T body) { return new A(); } private  A ok(Procedure action) { return new A(); } public  A ok() { return new A(); } @FunctionalInterface public interface Procedure { void invoke(); } } 

导致java9编译器出现以下错误::

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

这是一个错误。

据报道它有错误ID: JDK-8195598


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

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

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

但只是改变方法的顺序

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

使编译器接受代码而没有任何错误。

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

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

请注意,只要编译器接受代码,它就会认为ok(Supplier)ok(Runnable)更具体,这是与两者匹配的函数参数的预期行为。