The main difference between this two keywords is that when you use final, you explicitly write it before the name of the variable and you can’t change the value overtime. Wereas with effectively final, you declare as a normal variable and if you don’t change that value overtime it will become an effectively final variable:
import java.lang.FunctionalInterface;
@FunctionalInterface
interface Foo{
public String modifiesOutsideVariables(String s);
}
public static void main(String []args){
String outsideVariable = "P";
Foo f = (s) -> {
s="d"; //no problem
outsideVariable="insideValue"; // compiler will complain about :local variables referenced from a lambda expression must be final or effectively final
return s;
};
}
However if the value of an object is changed through an object method the compiler will not complain:
class Boo{
int a = 10;
public void modifyA(){
this.a = 11;
}
}
public static void main(String \[\]args){
final Boo b = new Boo();
Foo f = (s) -> {
b.modifyA(); //changing the value of object but not the refference : no errors
b = new Boo(); //this will break because the reference where b is pointing gets changed
s="d"; //no problem
return s;
};
}
A variable or parameter whose value is never changed after it is initialized is effectively final.