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