4

I just started working around lambda expression in Java 8. I'm bit confused about effectively final.

Local variable initialized once is effectively final but what about global variable, I can change value of global variable and use it in lambda expression. So what is the reason behind local variable should be effectively final. I couldn't find any articles or on javadoc about this.

import java.util.ArrayList;
import java.util.List;

public class Main {

    private String lastname = "Thakor";

    public static void main(String[] args) {
        Main objMain = new Main();
        objMain.test();
    }

    public void test(){
        List<String> listStrings = new ArrayList<String>();
        listStrings.add("Vicky");
        listStrings.add("Thakor");

        String middlename = "V";
        //Local variable middlename defined in an enclosing scope must be final or effectively final
        /* middlename = "T";*/ 

        /**
         * In case of global variable, why lambda expression not throwing error...
         * Local variable middlename defined in an enclosing scope must be final or effectively final
         */
        lastname = "T"; 

        listStrings.stream()
                        .forEach(firstname ->{
                            System.out.println("Firstname: " + firstname);
                            System.out.println("Middle: " + middlename);
                            System.out.println("Lastname: " + lastname);
                            System.out.println("--------------------------------------");
                        });
    }
}

Output

Firstname: Vicky
Middle: V
Lastname: T
--------------------------------------
Firstname: Thakor
Middle: V
Lastname: T
--------------------------------------
Vicky Thakor
  • 3,847
  • 7
  • 42
  • 67
  • possible duplicate of [Difference between final and effectively final](http://stackoverflow.com/questions/20938095/difference-between-final-and-effectively-final) – Jordi Castilla Jun 09 '15 at 09:56
  • 2
    @JordiCastilla, not really – shmosel Jun 09 '15 at 09:57
  • @JordiCastilla I know the difference but I'm asking about global variable. – Vicky Thakor Jun 09 '15 at 09:58
  • 1
    There are no global variables in Java. The instance variable is not in the (immediately) enclosing scope, it's just being used there. It's being accessed through a reference to the object itself. – Stultuske Jun 09 '15 at 09:59
  • @Vicky I can't recall the exact reason behind requiring local variables to be effectively final but I assume it has got something to do with threads using the local variables from the stack. – Chetan Kinger Jun 09 '15 at 10:00

1 Answers1

7

When you reference a "global" variable in a lambda, you're really capturing a reference to this, which is effectively final.

Consider the following snippet (untested):

class Main {

    class Box {
        int value;
    }

    void foo() {
        Box box = new Box();
        Runnable r = () -> box.value++;
    }
}

Even though you're changing the box.value, you're doing it through the box reference, which is effectively final. Similarly, you code is equivalent to

System.out.println("Lastname: " + this.lastname);

meaning you're accessing lastname through the this reference, which is effectively final.

shmosel
  • 49,289
  • 6
  • 73
  • 138
  • Sorry I'm not getting your answer. I'm still confused. – Vicky Thakor Jun 09 '15 at 11:22
  • @VickyThakor, which part are you stuck on? Do you understand the example snippet? – shmosel Jun 09 '15 at 16:58
  • `accessing lastname through the this reference` Why it refer the variable as `effectively final` when accessing through reference? What makes it different from local variables? Frankly I don't understand the logic behind it. Can you explain it how java treat it from compiler level to run time. – Vicky Thakor Jun 10 '15 at 05:21
  • @VickyThakor, I recently saw it put this way: Java closures close over *values*, not *variables*. `box` is a value. `this` is a value. `final` variables are effectively values. Allowing mutable variables to be referenced in a lambda would imply that the lambda captures the variable itself, not just its value. – shmosel Jun 10 '15 at 05:40
  • Global variable you can update, but cannot do for Final declared variable – Hemanth Peela Jan 30 '19 at 17:59