Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why lambda expressions in Java 8 requires variables used inside it to use "final" modifier, but not when using method reference? [duplicate]

Consider following class:

class Foo<T> {

    void handle(T t) {
        System.out.println("handling " + t);
    }

    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);

        Foo<Integer> f = new Foo<>();

        list.forEach(f::handle);             // compiles fine
        //list.forEach(obj -> f.handle(obj));// compilation error

        f = new Foo<>(); // reassign f

    }
}

Why do I get compilation error for obj -> f.handle(obj), but not for f::handle?

like image 466
Mateus Viccari Avatar asked Dec 22 '14 19:12

Mateus Viccari


People also ask

Why do local variables used in lambda have to be final or effectively final?

Forcing the variable to be final avoids giving the impression that incrementing start inside the lambda could actually modify the start method parameter.

Why are variables final in lambda Java?

The local variables that a lambda expression may use are referred to as “effectively final”. An effectively final variable is one whose value doesn't change after it's first assigned. There is no need to explicitly declare such a variable as final, although doing so would not be an error.

Why are lambdas expression used in Java 8?

In Java 8, using lambda expression and Stream API we can pass processing logic of elements into methods provided by collections and now collection is responsible for parallel processing of elements and not the client. Also, parallel processing effectively utilizes multicore CPUs used nowadays.

Can we use Non final local variables inside a lambda expression?

A lambda expression can use a local variable in outer scopes only if they are effectively final.


1 Answers

Those are two different constructs that are doing two different things. In the first case, you are getting the method reference of a specific object: this needs to be done only once, after which the JVM has its own reference (so effectively final) to the object f and can call the handle method. In the second case, at each call the JVM has to resolve the f reference and it thus complains that f must be final. You could easily write code that sets f to null while the forEach is running and thus cause a NPE.

like image 62
Giovanni Botta Avatar answered Oct 25 '22 23:10

Giovanni Botta