Monday, 14 March 2016

effectively final in Java 8

In Java 8 with the addition of lambda expressions, a new concept effectively final variable has been added, which closely relates to lambda expressions.

Prior to Java 8, inner classes had an important restriction that inner classes could only use variable from enclosing scope if it's final.

Example Code

Let's see an example code, where we have an interface IFunc, with one mthod display(). That interface is implemented as an anonymous class in Test class. In the implementation of display() method it tries to access the varibale i from the enclosing scope which is not declared as final variable. Note that this code is compiled and executed using Java 6.

interface IFunc{
  void display();
}

public class Test {

 /**
  * @param args
  */
 public static void main(String[] args) {
  int i =7;
  // Anonymous inner class
  new IFunc() {
   @Override
   public void display() {
    System.out.println("Value is " + i);
    
   }
  };
 }
}

Output

There will be a compile time error -

Cannot refer to a non-final variable i inside an inner class defined in a different method

Effectively final in Java 8

With Java 8 this restriction of declaring the variable in the enclosing scope as final has been eased a bit. If you are accessing a variable from the enclosing scope in an inner class (or lambda expression for that matter) you are not forced by compiler to declare that variable as final (though declaring the variable as final is still ok).

Note here that you still can't change the value of that variable. Doing so will result in "local variable defined in an enclosing scope must be final or effectively final" error.

Let's write the same code as above using Lambda expression in Java 8 now -

@FunctionalInterface
interface  IFunc{
    void display();
}

public class InnerDemo {
    
    public static void main(String[] args) {
        int i = 7;
        // lambda expression that implements the display method 
        // of the IFunc functional interface 
        IFunc ifunc = ()-> System.out.println("Value of i is " + i);
        // Calling the display method
        ifunc.display();
    }   
}

Output

Value of i is 7

It can be seen if you are not changing the value of local variable i, it can be used with lambda expression and there is no need to declare i as final.

With inner class also you won't get error now. If you'll compile the same code (inner class implementation) which was not running in Java 6, it will compile with Java 8.

What will give error

As already stated you still can't change the value of the variable used from the enclosed scope, trying to do that will result in error.

Example Code

If you try to change the value of i with in the lambda expression you'll get the error "Local variable i defined in an enclosing scope must be final or effectively final".

effectively final

Here it can be seen variable i from the enclosing scope is changed with in the lambda expression by trying to print i++. Thus compile time error is thrown that "Local variable i defined in an enclosing scope must be final or effectively final"

That's all for this topic effectively final in Java 8. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. final in Java
  2. interface static methods in Java 8
  3. interface default methods in Java 8
  4. Optional class in Java 8
  5. Functional interfaces & lambda expression
  6. How to resolve Local variable defined in an enclosing scope must be final or effectively final error

You may also like -

>>>Go to Java advance topics page

1 comment:

  1. Another great java articles and very interesting to read,thanks for sharing that wonderful useful information,given programming coding was very excellent and easily observe all provided information.
    php training in chennai

    ReplyDelete