Wednesday, 9 September 2015

How to resolve Local variable defined in an enclosing scope must be final or effectively final error

This post talks about how to resolve "local variable defined in an enclosing scope must be final or effectively final" error while trying to write a lambda expression.

Let's first get some background on what is effectively final; that will help you to get an idea why this error is coming.

Effectively Final

When a lambda expression uses an assigned local variable from its enclosing space there is an important restriction.
A lambda expression may only use local variable whose value doesn't change. That restriction is referred as "variable capture" which is described as; lambda expression capture values, not variables. The local variables that a lambda expression may use are known as "effectively final".
An effectively final variable is one whose value does not change after it is first assigned. There is no need to explicitly declare such a variable as final, although doing so would not be an error. Since there is no need to explicitly declare such a variable as final thus the name effectively final. If there is an attempt to change such a variable, anyway compiler will throw an error.

Let's see it with an example. Here I have a functional interface IFunc which has a single abstract method display. Since it has a single abstract method it is a functional interface and lambda expression can be used to implement this functional interface. Just to make it clear I have also used the @Functional interface annotation.
In the code lambda expression that implements the display method of the interface just prints the value of the local variable on the console. It can be noted that there is no need to declare variable i as final which was a requirement before Java 8 (in case of anonymous class).

@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 we 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.

When will it give error

As already pointed out while discussing effectively final "A lambda expression may only use local variable whose value doesn't change". So 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".

Code which will give compiler error

@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();
    }   
}

Here I have changed the i to i++ in System.out thus the program will give compiler error "Local variable i defined in an enclosing scope must be final or effectively final".

So it should be clear by now what it means for a variable to be effectively final and why do you get this error "local variable defined in an enclosing scope must be final or effectively final".

That's all for this topic How to resolve "Local variable defined in an enclosing scope must be final or effectively final" error. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Overview of lambda expressions
  2. Functional interfaces & lambda expression
  3. Functional interface annotation in Java 8
  4. Lambda expression and variable scope
  5. How to fix the target type of this expression must be a functional interface error

You may also like -

No comments:

Post a Comment