Saturday 14 July 2018

[solved] local variable defined in an enclosing scope must be final or effectively final

In this article we will see how to resolve local variable defined in an enclosing scope must be final or effectively final error for lambda expression.


Background


Java 8 introduces lambda expression which makes an easy way to implement interface which has only one abstract method (also known as functional interfaces). It is a requirement for lambda expression that if it is using local variable, it must be effective final. 


Meaning of Effectively final:


Effectively final are those variable which value doesn't change after it has been set. The sudden question that came in our mind that if this is the meaning of effectively final, why doesn't we declare the variable with final keyword. The difference between effectively final (its a terminology and not a java keyword) and keyword final is that effectively final behaves like final variable even it has not been declared final. 
If you declare a variable as final, its value cannot be changed (will throw compilation error) while those variable which value has been set once and never changed (without declaring as final) is called effectively final. This has to be taken care by developer if he is considering any variable as effectively final because compiler will not throw exception in this case, if the coder changes the value (not in context of lambda expression).


Code Example and Solution:


Consider the below code example which will give the following compilation error:
local variable defined in an enclosing scope must be final or effectively final


Code with Compilation error:



@FunctionalInterface

interface  SingleMethodInterface{

    void value();

}



public class Test {  

    public static void main(String[] args) {

        int i = 10; // This should be effectively final because it is being used by lambda expression.

        // If the value of i changes, it will throw the exception.

        // lambda expression implementing the value method. This is just implementation of interface

        // Here intentionally changing the value of i (increasing by one)

        SingleMethodInterface singleMethodInterface = ()-> System.out.println("Value of i is " + ++i); 

        // Calling the implemented interface method. Since the value is changed, so it will give compilation error

        singleMethodInterface.value();

    }

}


Code with no error


@FunctionalInterface

interface  SingleMethodInterface{

    void value();

}



public class Test {  

    public static void main(String[] args) {

        int i = 10; // This should be effectively final because it is being used by lambda expression.

        // If the value of i changes, it will throw the exception.

        // lambda expression implementing the value method. This is just implementation of interface

        // Here no changing the value of i

        SingleMethodInterface singleMethodInterface = ()-> System.out.println("Value of i is " + i); 

        // Calling the implemented interface method. Since the value is not changed so no error here

        singleMethodInterface.value();

    }

}


That's all for resolution of error for lambda expression with respect to local variable. If you have any further query, feel free to write out in comment section.

No comments:

Post a Comment