voz*_*zrr 5 java constructor-reference
像这样的代码
public class LambdaTest {
public static void main(String[] args) {
final Animal animal = Dog::new;
animal.eat();
}
}
@FunctionalInterface
interface Animal {
void eat();
}
class Dog implements Animal {
public Dog() {
System.out.println("dog init.");
}
@Override
public void eat() {
System.out.println("dog eat");
}
Run Code Online (Sandbox Code Playgroud)
当我运行这段代码时,“dog init”。被打印到控制台,但“dog eat”却没有。这是为什么?有人能告诉我原因吗?
我预计会打印“dog init”和“dog eat”,但只打印了“dog init”。另外,我很困惑为什么在Animal animal = Dog::new;.
Animal是一个具有单一方法void eat()(void 返回,无参数)的函数式接口 \xe2\x80\x93 也称为SAM 类型(单一抽象方法)。
java.util.Runnable它在结构上与接口( )相同interface Runnable { void run(); }。你的代码也可以写成:
final Runnable runnable = Dog::new;\nrunnable.run(); // calls the constructor\nRun Code Online (Sandbox Code Playgroud)\n您可以为其分配任何具有零参数且无返回值的 lambda 或方法引用,例如() -> {}.
Dog::new是一个方法引用,相当于 lambda() -> { new Dog(); }. If you look closely, you will notice that this lambda does not return anything. It constructs a new Dog instance and then forgets about it again.
将方法引用或 lambda 分配给变量并不会执行它(尚未)。您必须通过从接口调用命名方法来显式调用 lambda。
\n现在,您animal是Animal接口的一个实例,并被分配了一个方法引用,稍后可以调用该方法引用。animal.eat() invokes the assigned method reference, calling the constructor.
如果您希望变量animal保存一个Dog实例,然后调用eat它的方法,请直接调用构造函数:Animal animal = new Dog();
“问题”是您的方法的签名eat,因为它相当于Runnable#run并允许分配任何“空”操作。
Lambda 和方法引用是在 Java 8 中引入的。在之前的 Java 版本中,您必须创建一个匿名类才能实现相同的行为:
\nfinal Animal animal = new Animal() {\n @Override public void eat() {\n new Dog();\n }\n};\nanimal.eat(); // calls "eat" of the anonymous instance, which in turn calls the constructor; does NOT call `Dog#eat`\nRun Code Online (Sandbox Code Playgroud)\n