Tuesday, July 27, 2021

What is Effectively Final variable of Java 8? Example

Apart from the big three, Lambda expression, Stream API, and new Date and Time API, Java 8 has also introduced a new concept called the "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 the 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, it's just that you don't need to use the final keyword anymore, saving a few keystrokes.

If you don't follow this then you will get the 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 makes the life of Java developers easy.

Btw, if you are not familiar with new Java 8 features like Effectively final variable then I suggest you first go through comprehensive and up-to-date Java courses from Udemy and Coursera. These are good resources to learn new Java features. 


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 designers to us, Java developers. There is hardly any difference between a final local variable and an effectively final variable, once declared you cannot change the values of both of them.

If you do, the compiler will raise an error. Here is an example of using an effectively 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() {
            @Override
            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);
        t.start();
    }

}

If you run this program it will print the 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 an 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);
        t.start();
    }

}

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 the 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 is only available from Java 8 onward. A variable is considered an effective final if it is not modified after initialization in the local block.

This means you can now use the local variable without the final keyword inside an anonymous class or lambda expression, provided they must be effectively final. In short, you can save some keystrokes while declaring local final variables intended to be used by the anonymous class.

There is no real difference between a final local variable and an effectively final variable of Java 8, once initialized you cannot change the value of both of them.

If you like this tutorial and are hungry to learn more about new features and goodies from Java 8, check out the 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 the 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)

4 comments :

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