简体   繁体   English

具有功能接口的Java-8 lambda表达式行为

[英]Java-8 lambda expressions behaviour with functional Interface

I was just trying out few java-8 functional programming , I had few doubts on the behaviour of the lamda expressions. 我只是尝试了几个java-8函数式编程,我对lamda表达式的行为几乎没有怀疑。 I have tried to explain the problem below with simple Command Pattern. 我试图通过简单的命令模式来说明以下问题。

public interface Editor {
    public void open();
    public void close();
//  public void save();

}

Editor Implementation 编辑器实施

public class MyEditor implements Editor {

    @Override
    public void open() {
        System.out.println("...opening");

    }

    @Override
    public void close() {
        System.out.println("...closing");
    }

}

Interface Action 界面动作

// this is actually a @FunctionalInterface
public interface Action {
    public void perform();

}

Actionable items. 可行的物品。

public class Open implements Action {

    private final Editor editor;

    public Open(Editor editor) {
        this.editor = editor;
    }

    @Override
    public void perform() {
        editor.open();
    }

// Similarly Close implements Action...

... ...

A Macro to run all the actions. 用于运行所有操作的宏。

public class Macro {

    private final List<Action> actions;

    public Macro() {
        actions = new ArrayList<>();
    }

    public void record(Action action) {
        actions.add(action);
    }

    public void run() {
        actions.forEach(Action::perform);
    }
}

Now running the Macro is where the interesing part is . 现在,运行宏是交互部分所在的位置。

public class RunMacro {
    public static void main(String[] args) {
        Editor editor= new MyEditor();
        Macro macro = new Macro();
        macro.record(() -> editor.open());// Line 4
        macro.record(new Close(editor));  // Line 5
        macro.run();
    }
}

My question is , during the execution of Line 4, How does Java understand that to create a instanceof Open and add it into macro. 我的问题是,在第4行的执行过程中,Java如何理解创建instanceof并将其添加到宏中。 In short lamdba expressions is behaving same way as Line 5. This whole pattern becomes a lot simpler with lambda expressions BUT does the functional programming with OOPS makes the development at very abstract level or less verbose? 简而言之,lamdba表达式的行为方式与第5行相同。使用lambda表达式,整个模式变得更加简单但是,使用OOPS进行功能编程是否会使开发变得非常抽象或不太冗长?

Courtesy of problem : O'Reilly Media : Java 8 Lamdbas 问题的礼貌:O'Reilly媒体:Java 8 Lamdbas

Could any one please clarify this.? 有人可以澄清一下吗?

How does Java understand that to create a instanceof Open and add it into macro ? Java如何理解如何创建Open的实例并将其添加到宏中?

You should read the section Target Typing in Lambda Expressions of the java tutorial. 您应该阅读Java教程的Lambda表达式中的目标类型部分。 When you wrote: 你写的时候:

macro.record(() -> editor.open());

Your are not creating an instance of the Open class. 您没有创建Open类的实例。 You are not creating an instance of a generated anonymous class. 您没有创建生成的匿名类的实例。

See Translation strategy section in Translation of Lambda Expressions . 请参阅Lambda表达式的翻译中的 Translation strategy部分。

Instead of generating bytecode to create the object that implements the lambda expression (such as calling a constructor for an inner class), we describe a recipe for constructing the lambda, and delegate the actual construction to the language runtime. 我们不是生成字节码来创建实现lambda表达式的对象(例如调用内部类的构造函数),而是描述构造lambda的配方,并将实际构造委托给语言运行库。 That recipe is encoded in the static and dynamic argument lists of an invokedynamic instruction. 该配方在invokedynamic指令的静态和动态参数列表中进行编码。


You could also take advantages of the java 8 method references , and simplify again the code: 您还可以利用java 8 方法引用 ,并再次简化代码:

    Editor editor= new MyEditor();
    Macro macro = new Macro();
    macro.record(editor::open);
    macro.record(editor::close);
    macro.run();

at last you may remove the Action interface and use the Runnable one. 最后,您可以删除Action界面并使用Runnable界面。 This allow for example to use all the stuff of the java.util.concurrent like Executor , the new java promise: CompletableFuture ... 例如,这允许使用java.util.concurrent所有内容,例如Executor ,新的Java承诺: CompletableFuture ...

Lambda constructs are a very readable replacement for a construct that is a long-time part of the Java language: anonymous classes . Lambda构造是Java语言中长期存在的构造: 匿名类的一种非常易读的替代。 In fact, regarding the intention you can think of a lambda expression as an anonymous class, although technically there is a big difference. 实际上,就技术意图而言,您可以将lambda表达式视为一个匿名类,尽管在技术上存在很大差异。

Just to add a third variant for your record method: 只是为您的record方法添加第三个变体:

macro.record(new Action() {
    @Override public void perform() { editor.open(); }
});

Here you are passing an instance of an anonymous class (a subclass of Action ) to the recording method. 在这里,您将一个匿名类( Action的子类)的实例传递给记录方法。 This is the same with the lambda expression: 这与lambda表达式相同:

macro.record(() -> editor.open());

For these two variants you even do not need the Open class. 对于这两个变体,您甚至不需要Open类。 Try it out and remove it from the sources. 尝试一下,将其从源中删除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM