Java 方法引用选择窄类型



我想知道为什么下面的代码使用 Object 参数而不是 int 执行该方法:

public class Main {
public static void main(String[] args) {
java.util.function.Consumer bla = new Bla()::shake;
bla.accept(6);
}
}
class Bla {
void shake(int i) {
System.out.println("shake called with i " + i);
}
void shake(Object o) {
System.out.println("shake called with o " + o);
}
}

输出:

用 O 6 调用的摇晃

关键是:您没有直接调用该shake()方法。

您正在通过消费者界面!

该接口显示accept(T t)其中 T 是引用类型泛型!但是您使用的是原始类型,因此 T 变成了 Object! 不幸的是,即使使用"正确"的泛型类型 Integer,它也不起作用!

所以,是的,正如 Eran 首先指出的那样,解决方案是使用 instaed 的IntConsumer界面!

那是因为您使用的是原始Consumer类型,该类型会消耗Object

使用Consumer<Integer>

Consumer<Integer> bla = new Bla()::shake;

但是,您必须将第一个方法签名更改为void shake(Integer i),以便它与Consumer<Integer>功能接口匹配。

如果要使用原始void shake(int i)方法使用int,请使用IntConsumer

java.util.function.IntConsumer bla = new Bla()::shake;
Consumer bla = new Bla()::shake;

相当于

Consumer<Object> bla = new Bla()::shake;

相当于 (*(

Consumer<Object> bla = (Object x) -> new Bla().shake(x);

即使您指定了预期的泛型类型参数Integer,即

Consumer<Integer> bla = new Bla()::shake;

它相当于

Consumer<Integer> bla = (Integer x) -> new Bla().shake(x);

Java 方法解析分为 3 步搜索:

  1. 在不使用装箱、拆箱或变量参数的情况下进行匹配。

  2. 使用装箱
  3. 和取消装箱进行匹配,但没有变量参数。

  4. 全部匹配。

由于shake(Object)在第一步中匹配,因此即使对于Integer类型参数,这也是使用的方法。

要获得shake(int)重载,您必须删除shake(Object)重载,或传递一个基元整数值(byteshortcharint(,这意味着您可以通过以下方式之一使其工作:

Consumer<Integer> bla = x -> new Bla().shake((int) x);
Consumer<Integer> bla = x -> new Bla().shake(x.intValue());
IntConsumer bla = new Bla()::shake;    // Recommended solution

(*( 它并不完全等价:它更像是:

Bla instance = new Bla();
Consumer<Object> bla = (Object x) -> instance.shake(x);

上面省略了此详细信息,以重点介绍方法签名解析。

最新更新