It seems that Java lambda expressions can access local variables that are ** practically final **. The reference book said, "Variables that do not change even if they are not qualified with ** final **."
"It doesn't come with ** final **, but it hasn't changed at all since it was declared, so it's the same as ** final **!"
In this case, the local variable ʻi` is practically final,
LambdaStudy.java
public class LambdaStudy {
public static void main(String[] args) {
int i = 10;
Calculate c = x -> x + i;
System.out.println(c.calc(20));//30
}
}
interface Calculate {
public int calc(int x);
}
In this case, since the value of ʻi` has been changed by incrementing, it is not practically final and a compile error occurs.
LambdaStudy.java
public class LambdaStudy {
public static void main(String[] args) {
int i = 10;
i++;
Calculate c = x -> x + i;//Local variable i defined in an enclosing scope must be final or effectively final
System.out.println(c.calc(20));
}
}
interface Calculate {
public int calc(int x);
}
It does not change even if it is a reference type.
In this case, sb
is becausesb.append ("d")
is only changing the referenced object of the variable sb
, not the variable sb
itself. It becomes practically final and can be executed.
LambdaStudy.java
public class LambdaStudy {
public static void main(String[] args) {
int i = 10;
StringBuilder sb = new StringBuilder("abc");
sb.append("d");
Calculate c = x -> {
System.out.println(sb.toString());//abcd
return x + i;
};
System.out.println(c.calc(20));//30
}
}
interface Calculate {
public int calc(int x);
}
If you reassign to sb
, the reference destination of sb
will change, so it will not be practically final. (Compile error)
LambdaStudy.java
public class LambdaStudy {
public static void main(String[] args) {
int i = 10;
StringBuilder sb = new StringBuilder("abc");
sb.append("d");
sb = new StringBuilder("efg");
Calculate c = x -> {
System.out.println(sb.toString());//Local variable sb defined in an enclosing scope must be final or effectively final
return x + i;
};
System.out.println(c.calc(20));
}
}
interface Calculate {
public int calc(int x);
}
Substantially final variables are ** "variables that have not changed at all since the variable was declared" **.
Recommended Posts