Lambda expression using a final field in object initialization block
Jaikiran Pai
jai.forums2013 at gmail.com
Mon Mar 4 09:56:28 UTC 2019
Please consider this trivial code:
import java.util.Map;
import java.util.HashMap;
import java.util.function.Supplier;
public class LambdaTest {
private final String name;
private final Map<String, Supplier<String>> suppliers = new HashMap<>();
{
this.suppliers.put("a", () -> name);
}
private LambdaTest(final String name) {
this.name = name;
}
public static void main(final String[] args) throws Exception {
final LambdaTest self = new LambdaTest("hello");
}
}
When I compile this with Java 8 (javac 1.8.0_172) and even Java 11
(javac 11.0.1), I get a compilation error, in the object initialization
block where I am using a lambda expression to populate the "suppliers"
Map and am referring to a final field (called "name") of the class. The
compilation error is:
LambdaTest.java:12: error: variable name might not have been initialized
this.suppliers.put("a", () -> name);
^
1 error
Now, if I replace that piece of code with:
import java.util.Map;
import java.util.HashMap;
import java.util.function.Supplier;
public class LambdaTest {
private final String name;
private final Map<String, Supplier<String>> suppliers = new HashMap<>();
{
this.suppliers.put("a", new Supplier<String>() {
@Override
public String get() {
return name;
}
});
}
private LambdaTest(final String name) {
this.name = name;
}
public static void main(final String[] args) throws Exception {
final LambdaTest self = new LambdaTest("hello");
}
}
The only change in this is the object initialization block, where I no
longer use a lambda and instead use an anonymous class. This passes
compilation successfully.
Why is it an error to use such a final field in a lambda expression? The
(basic) documentation[1] of Lambda expressions doesn't seem to mention
this construct as invalid.
[1]
https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
-Jaikiran
More information about the jdk-dev
mailing list