我想知道为什么下面的代码使用 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 步搜索:
- 使用装箱
在不使用装箱、拆箱或变量参数的情况下进行匹配。
和取消装箱进行匹配,但没有变量参数。
全部匹配。
由于shake(Object)
在第一步中匹配,因此即使对于Integer
类型参数,这也是使用的方法。
要获得shake(int)
重载,您必须删除shake(Object)
重载,或传递一个基元整数值(byte
、short
、char
或int
(,这意味着您可以通过以下方式之一使其工作:
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);
上面省略了此详细信息,以重点介绍方法签名解析。