首先,我不知道如何得体地表达这个问题,所以这是我的建议.

假设我们有以下重载方法:

void execute(Callable<Void> callable) {
    try {
        callable.call();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

<T> T execute(Supplier<T> supplier) {
    return supplier.get();
}

void execute(Runnable runnable) {
    runnable.run();
}

从这张桌子上下来,我得了another SO question

Supplier       ()    -> x
Consumer       x     -> ()
BiConsumer     x, y  -> ()
Callable       ()    -> x throws ex
Runnable       ()    -> ()
Function       x     -> y
BiFunction     x,y   -> z
Predicate      x     -> boolean
UnaryOperator  x1    -> x2
BinaryOperator x1,x2 -> x3

以下是我在当地得到的结果:

// Runnable -> expected as this is a plain void  
execute(() -> System.out.println()); 

// Callable -> why is it not a Supplier? It does not throw any exceptions..
execute(() -> null);

// Supplier -> this returns an Object, but how is that different from returning null?
execute(() -> new Object());

// Callable -> because it can throw an exception, right?
execute(() -> {throw new Exception();});

编译器如何知道调用哪个方法?

推荐答案

我相信我已经找到了官方文件中描述的地方,尽管有点难读.

提到Here:

15.27.3. Lambda表达式的类型

请注意,虽然在严格的调用上下文中不允许装箱,

然后分析性地描述了如何 Select 最具体的方法.

根据这个例子

一种适用方法m1比另一种适用方法更具体

m2是通用的,m1被推断为比m2更具体

所以

// Callable -> why is it not a Supplier?
execute(() -> null);   <-- Callable shall be picked from 2 options as M2 is generic and M1 is inferred to be more specific

void execute(Callable<Void> callable) {  // <------ M1 
   try {
    callable.call();
  } catch (Exception e) {
      e.printStackTrace();
  }
}


 <T> T execute(Supplier<T> supplier) {  // <------ M2 is Generic
    return supplier.get();
 }

M1被推断为更具体的原因可以从here (18.5.4 More Specific Method Inference)描述的这个过程中追溯

Java相关问答推荐

Java中Stream(java.util.stream)和linkedList数据 struct 之间是什么关系?

Collections.binarySearch()使用Collections.reverseOrder()作为比较器返回-1

将偶数元素移动到数组的前面,同时保持相对顺序

如何为具有多对多关系的实体的给定SQL查询构建JPA规范?

Javascript在边界中心调整ImageView大小

如何在带有Micronaut的YAML中使用包含特殊字符的字符串作为键

调用引发泛型异常的泛型方法时出现编译错误

Chunk(Int)已弃用并标记为要删除

SpringBoot Kafka自动配置-适用于SASL_PLAYTEXT的SSLBundle 包,带SCRAM-SHA-512

为什么我的回收视图会显示重复的列表?

如何仅使用键/ID的一部分(组合)高效地返回映射值?

扩展视图高度,并将其拖动到较低的视图上,而不是将其向下推?

使用Jackson库反序列化json

Java在操作多个属性和锁定锁对象时使用同步和易失性

如何从命令行编译包中的所有类?

在线程Java中调用Interrupt()之后调用Join()

";home/runner/work/中没有文件...匹配到[**/pom.xml];Maven项目的构建过程中出现错误

spring 更新多项管理关系

java21预览未命名的符号用于try-with-resources

";重复键的值提示唯一约束«;livre_genre_pkey»";例外