Overview
Java Lambda implemented in version 8 is a function that a definition of a method can be described as an expression.
Before Java8
Programmers must have implemented an interface to pass logic codes.
public class Main {
    interface IGreeter {
        void greet(String name);
    }
    static void delegate(IGreeter iGreeter, String name){
        iGreeter.greet(name);
    }
    public static void main(String[] args) throws Exception {
        // need to put an object implemented the interface 'IGreeter'
        delegate(new IGreeter(){
            public void greet(String name){
                System.out.println("Hello, " + name + "."); // => Hello, Taro.
            }
        }, "Taro");
    }
}
From Java8
That can be written simpler than before, and it increased the readability for programmers.
public class Main {
    interface IGreeter {
        void greet(String name);
    }
    static void delegate(IGreeter iGreeter, String name){
        iGreeter.greet(name);
    }
    public static void main(String[] args) throws Exception {
        // The below callings print 'Hello, Taro.'
        delegate((name) -> {System.out.println("Hello, " + name + ".");}, "Taro"); // (arg) -> {sentences}
        delegate(name -> {System.out.println("Hello, " + name + ".");}, "Taro"); // arg -> {sentences}  #if only having one arg, it can omit ()
        delegate(name -> System.out.println("Hello, " + name + "."), "Taro"); // arg -> expression
    }
}
"This" reference
Between a Lambda method and an anonymous interface, the meanings of "this" reference are different, be careful.
public class Main {
    private final String value = "aaa";
    interface IPrinter {
        void printValue();
    }
    void delegate(IPrinter iPrinter){
        iPrinter.printValue();
    }
    void callDelegate(){
        delegate(() -> System.out.println("value => " + this.value)); // value => aaa
    }
    public static void main(String[] args) throws Exception {
        // 1) Lambda expression
        new Main().callDelegate(); 
        // 2) Anonymous interface
        new Main().delegate(new IPrinter(){
            private final String value = "bbb";
            public void printValue(){
                System.out.println("value => " + this.value); // value => bbb
            }
        }); 
    }
}
Accessible variables
From Lambda expression, Substantially 'final' variables can be accessed.
Even without 'final' keyword, if the value is not changed, it is accessible.
public class Main {
    interface IPrinter {
        void printValue();
    }
    static void delegate(IPrinter iPrinter){
        iPrinter.printValue();
    }
    public static void main(String[] args) throws Exception {
        int aaa = 100;
        delegate(() -> System.out.println(aaa)); // 100
        //aaa = 200;
        //If the above sentence is uncommented, a compile error will occur with the below error message.
        //Main.java:14: error: local variables referenced from a lambda expression must be final or effectively final
    }
}
Stateful Lambda expression
If you would like to have a Lambda expression with state, there are two ways.
1) Use instance field
public class Main {
    interface ICounter {
        int nextValue();
    }
    private int count; // the default value is zero
    ICounter makeCounter(){
        return () -> count++;
    }
    public static void main(String[] args) throws Exception {
        ICounter iCounter = new Main().makeCounter();
        System.out.println(iCounter.nextValue()); // 0
        System.out.println(iCounter.nextValue()); // 1
        System.out.println(iCounter.nextValue()); // 2
    }
}
2) Use referred object
public class Main {
    interface ICounter {
        int nextValue();
    }
    private int count; // the default value is zero
    ICounter makeCounter(){
        // https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicInteger.html
        AtomicInteger count = new AtomicInteger();
        return () -> count.getAndIncrement();
    }
    public static void main(String[] args) throws Exception {
        ICounter iCounter = new Main().makeCounter();
        System.out.println(iCounter.nextValue()); // 0
        System.out.println(iCounter.nextValue()); // 1
        System.out.println(iCounter.nextValue()); // 2
    }
}
Reference
改訂2版 パーフェクトJava
https://gihyo.jp/book/2014/978-4-7741-6685-8
 
 
              
 
    
Top comments (0)