Thursday, March 30, 2017

What is Effectively Final variable of Java 8

Apart from big three, Lambda expression, Stream API and new Date and Time API, Java 8 has also introduced a new concept called "effectively final" variable. A non-final local variable or method parameter whose value is never changed after initialization is known as effectively final. It's very useful in the context of the lambda expression. If you remember, prior to Java 8, we cannot use a non-final local variable in an anonymous class. If you have to access a local variable ( a method parameter or a variable decreed in the method itself) in Anonymous class, you have to make it final. This restriction is relaxed a bit with lambda coming up. Java designers have taken the need to make local variable final if it's not changed once initialized. This is really a good proactive step from them, they must have anticipated frequent use of lambda expressions as compared to the minimal use of Anonymous class and realized the pain to declare a local variable final every time in order to access it inside the lambda. The rule has not changed, any local variable still has to be effectively final to be used inside lambda expression or anonymous inner class, its just that you don't need to use final keyword anymore, saving a few keystroke. If you don't follow this then you will get following error: "local variables referenced from a lambda expression must be final or effectively final". Let's see some examples of effectively final variables with lambdas and anonymous class and how it make the life of Java developer easy. You can also read Cay S. Horstmann's Java SE 8 for Impatient to learn more about Effectively final variables in Java 8.

How to use Effective final variable in Java 8

Effectively Final variable of  Java 8
The effective final variable is nothing but a gift from Java designer to us, Java developers. There is hardly any difference between a final local variable and an effectively final variable, once declared you cannot change values of both of them. If you do, the compiler will raise error. Here is an example of using an effective final variable in Java 8, if you run the same program with Java source 1.7, your program will not compile and give error "local variable nonFinal is accessed from within inner class; needs to be declared final" because nonFinal is a local variable but not final. BTW, if you run the same program in Java 8 it will run fine and produce the output in the form of the print statement we have given. Now in Java 8, if you try to reassign a new value to our non-final local variable, the compiler will again complain about the error "local variables referenced from an inner class must be final or effectively final". This line is commented in our example, you can try by yourself by uncommenting it.

package test;

 * Java Program to demonstrate effectively final variable in Java 8.
 * @author Javin Paul
public class EffectiveFinalDemo{

    public static void main(String args[]) {
        String nonFinal = "I am non final local variable";
        Runnable r = new Runnable() {
            public void run() {
                System.out.println("Using non-final local variable inside anonymous class in Java");
                System.out.println("Value of non-final variable is : " + nonFinal);

                // compile time error - must be final or effective final
                // nonFinal = "Can I change non-final variable inside anonymous class";

        Thread t = new Thread(r);


If you run this program it will print following line in Java 8:
Using non-final local variable inside anonymous class in Java
Value of non-final variable is : I am non final local variable

Now let's see how to use effectively final variable in lambda expression in Java 8:
public class EffectiveFinalWithLambda{

    public static void main(String args[]) {
        String effectiveFinal = "I am non final local variable";
        Runnable r = () -> {
            System.out.println("Value of effectively variable is : " + effectiveFinal);

        Thread t = new Thread(r);


You can see that we can access "effectiveFinal" variable without any issue in the lambda expression. Now just try to assign this variable a new value before lambda, just to make it non-final and see what happens, you will receive an error "local variables referenced from a lambda expression must be final or effectively final".

That's all about what is effectively final variable of Java 8 and how to use it in your Java program. Now it becomes one more thing to note about final variables in Java. Remember till Java 7, you cannot use a non-final local variable inside an anonymous class, but from Java 8 you can.  The concept of Effective final variables in only available from Java 8 onward. A variable is considered effective final if it is not modified after initialization in the local block. This means you can now use the local variable without final keyword inside an anonymous class or lambda expression, provided they must be effectively final. In short, you can save some keystroke while declaring local final variables indented to be used by the anonymous class. There is no real difference between a final local variable and effectively final variable of Java 8, once initialized you cannot change the value of both of them.

Further Learning
The Complete Java MasterClass
From Collections to Streams in Java 8
Refactoring to Java 8 Streams and Lambdas Self- Study Workshop
If you like this tutorial and hungry to learn more about new features and goodies from Java 8, check out my following amazing articles:
  • 10 Good Tutorials to Learn Java 8 (list)
  • How to filter List in Java 8 using Predicates? (solution)
  • Java 8 Comparator Example with Lambdas (example)
  • 10 Java 7 Feature to revisit before you start with Java 8 (list)
  • How to Read File in Java 8 in one line? (example)
  • What is default method in Java 8. (tutorial)
  • How to use Map function in Java 8 (example)
  • 10 Examples of Stream API in Java (examples)
  • How to use Lambda Expression in Place of Anonymous class in Java 8 (solution)
  • Java 8 tutorials and Books for FREE (resources)
  • Are you ready for Java 8 Certification? (read more)
  • Java SE 8 for Really Impatient (book)


Anonymous said...

Some additional questions I have that your article dos NOT cover. I am using Java 8, but I cannot get final or effectively final String variables to work as method parameters with lambda expressions. Why ?

This works:

final String finalString = "hello.wav";
JButton soundButton = new JButton (finalString);
soundButton.addActionListener (event -> playSound (finalString));

But, if I try and use a FINAL array os Strings it does not work - I get *the* error. Why ?

sanjay said...

Where is the main part, "why" ?

Javin Paul said...

Can you please elaborate Sanjay, not very clear what do you mean ...

Achint Mittal said...

@Sanjay :

On "why" part, it's because a lambda expression can be used multiple times. Now, if you change the value of effectively final variable, then lambda expression cannot decide which value to use for that local variable. Hope this answers your question.

Post a Comment