How this code can be executed and compiled if at action.perform, the perform method is not even defined. And plus a command like editor at the time m.record(editor::save); , and the macro list itself is assigned to action type objects? How can this be?

 public class Macro { List<Actiona> macro; Macro(){ macro = new ArrayList<>(); } public void record(Actiona action){ macro.add(action); } public void run(){ macro.forEach(Actiona::perform); } public static void main(String[] args) { MockEditor editor = new MockEditor(); Macro m = new Macro(); m.record(editor::save); m.record(editor::close); m.run(); } } public class MockEditor implements Editor { @Override public void save() { System.out.println("Save"); } @Override public void close() { System.out.println("close"); } } public interface Actiona { public void perform(); } public interface Editor { public void save(); public void close(); } 

    1 answer 1

    This magic is easy to understand if you go to the IDE (say IDEA) and ask to replace the lamda with an anonymous class:

     public static void main(String[] args) { MockEditor editor = new MockEditor(); Macro m = new Macro(); m.record(new Actiona() { // вместо m.record(editor::save); @Override public void perform() { editor.save(); } }); m.record(new Actiona() { // вместо m.record(editor::close); @Override public void perform() { editor.close(); } }); m.run(); // Вызываем метод с двумя объектами Actiona 

    And suddenly everything becomes simple and clear, we implement the perform method by calling the editor.save() and editor.close() methods inside, so the behavior is quite correct.

    Very good skill, as soon as you get confused in lambda functions, replace them mentally (or using IDE) with anonymous classes and it becomes easier to live.