2

The reason for a local variable to be final or effectively final this because of concurrency issues. In the jls 8 specification, it states the following.

The restriction to effectively final variables prohibits access to dynamically-changing local variables, whose capture would likely introduce concurrency problems.

All good and sweet, but I did a little experiment. What if I synchronize the method, that would eliminate the possibility of dynamically-changing local variable because I am guaranteed only a single thread can execute this code. But the compile threw an error saying it has to be final or effectively final.

Is logic right?

Consider the following code:

    public synchronized void capture() {

        int localVariable = 100;

        Interf i = (text) -> System.out.println(text + localVariable);

        i.m1("This local variable is: ");

        localVariable = 1000;
    }
}
4
  • 1
    Are you sure the method you pass the lambda to doesn't use a different thread? Or execute the lambda sometime later? Consider SwingUtils.invokeLater(() -> System.out.println(localVariable)). What should this print? Commented Oct 2, 2019 at 20:12
  • the rules about final/effectively final is not causes by concurrency. It is causes by pass by value. The lambda gets a copy. If the copy is changed in the lambda or outside, both copies will have a different value. Commented Oct 2, 2019 at 20:17
  • 2
    synchronized on method would gaurantee the method is called by a single thread. But it does not gaurantee the method itself creating new threads within, does it? Commented Oct 2, 2019 at 20:33
  • suppose the lambda creates a Future to be executed by the forkjoinpool or another executor. Commented Oct 20, 2020 at 5:45

3 Answers 3

1

The answer is simply that your variable goes out of scope at the end of the method. This is easily solved with effectively final variables as the compiler just copies the value into the lambda. Since the code in the lambda expression can also be run outside of the method (where the modifiable variable is garbage collected already) this won't work. You also can't expect the compiler to somehow make a copy of your variable and then dynamically change it when it's modified outside of your lambda expression. I hope that clears it up.

Sign up to request clarification or add additional context in comments.

Comments

0

But the compile threw an error saying it has to be final or effectively final.

That's because it does as per the rules. No it's, no buts; it doesn't matter if you've actually guarded against all concurrency issues or not - if it's not effectively final, it won't compile.

In your simplistic example here it's probably ok. However, making the method synchronized is irrelevant since local variables will always be tied to their per-thread invocation anyway. It's threading issues within the context of the method itself that the compiler is worried about, and that can easily happen with lambdas being used (which may be executed some arbitrary time in the future, after the state of a non-final variable may have changed, and if it has, it's not at all clear what state should be used - the initial state, or the updated state.)

1 Comment

It's threading issues within the context of the method itself that the compiler is worried about I see that is true, can you give me an example for me to solidify this? Also, the thread issue you mentioned, are you saying that IF lambda expression can alter local variables, other thread don't get the visibility because the locals are thread private
0

Imagine the lambda that you have creates a CompletableFuture to be executed by the ForkJoinPool or another executor?

That is why synchronized on this method would not suffice to overrule the rule of having the local variable effectively final. The lambda will execute synchronously and will be synchronized but the async task that it creates would not.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.