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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从java8迁移到java9时,对方法的引用是不明确的相关的知识,希望对你有一定的参考价值。

我正在将项目从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);
 }

Procedure接口的代码:

@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)
答案

This is a bug.

据报道有错误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);
    }
}

这在使用“reference to ok is ambiguous”的Java 9的发布版本中失败,说明“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)更具体,这是与两者匹配的函数参数的预期行为。

以上是关于从java8迁移到java9时,对方法的引用是不明确的的主要内容,如果未能解决你的问题,请参考以下文章

JAVA8新特性——方法引用

将Spring Boot应用程序迁移到Java9:兼容性

java9新特性:在接口中用pirvate方法让default(java8接口特性)更简练

java8 java9 接口 interface

java8-从Lamda到方法引用和构造引用

关于intellij的Java 9迁移问题与模块系统有关