Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/389.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java方法引用选择窄类型_Java - Fatal编程技术网

Java方法引用选择窄类型

Java方法引用选择窄类型,java,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.pr

我想知道为什么下面的代码使用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);
    }
}
输出:

用o6呼叫shake


这是因为您使用的是原始
使用者
类型,它使用
对象

使用
消费者

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

关键是:您不是在直接调用
shake()
方法

您正在通过消费者界面

这个接口说,
accept(T)
,其中T是一个引用类型泛型!但是您使用的是原始类型,因此T会变成Object! 不幸的是,即使使用“正确的”泛型类型Integer,它也无法工作

因此,是的,正如Eran首先指出的,解决方案是使用
IntConsumer
接口instaed

Consumer bla = new Bla()::shake;
相当于

Consumer<Object> bla = new Bla()::shake;
Consumer<Integer> bla = (Integer x) -> new Bla().shake(x);
相当于

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

(*)不完全相同:更像:

Bla instance = new Bla();
Consumer<Object> bla = (Object x) -> instance.shake(x);
Bla实例=新建Bla();
消费者bla=(对象x)->instance.shake(x);

上面省略了这个细节,重点是方法签名解析。

提示:不要使用原始类型。。。因为
Consumer
是泛型的,所以它的参数是引用类型。请注意,即使使用
Consumer
这也会调用对象重载,因为您可以执行
Consumer.accept(null)
@Minn也相应地更新了。使用原始类型和默认类型之间存在一些差异。我一时记不起来了,但它们不时会出现。@matt Raw类型在编译器中禁用类型参数匹配,因此例如
Consumer
Consumer
彼此不兼容赋值,但
Consumer
两者都兼容赋值,即使从技术上讲这三个变量都编译成相同的字节码(作为局部变量)。“相当于…
->new Bla().shake(x)
”所有这些变量都应该在lambda之外有
new Bla()
。@AndyTurner True。“我试图保持它的简单性,把重点放在方法签名解析上。”安德烈亚斯补充了一个脚注。
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);