DEV Community

Cover image for Java Lambda expression
Yasushi Takehara
Yasushi Takehara

Posted on • Updated on

Java Lambda expression

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");
    }
}
Enter fullscreen mode Exit fullscreen mode

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
    }
}
Enter fullscreen mode Exit fullscreen mode

"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
            }
        }); 

    }
}
Enter fullscreen mode Exit fullscreen mode

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
    }
}
Enter fullscreen mode Exit fullscreen mode

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
    }
}
Enter fullscreen mode Exit fullscreen mode

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
    }
}
Enter fullscreen mode Exit fullscreen mode

Reference

改訂2版 パーフェクトJava
https://gihyo.jp/book/2014/978-4-7741-6685-8

Top comments (0)