Java 8 supplier behaviour: final variable might not be initialized

kristjank :

Java disallows usage of final variable inside a supplier as it might not be initialized, yet prepending "(this)." to variable makes it compile and run fine.

Furthermore calling such supplier results in NullPointerException instead of compiler error if called before assigning the variable and runs as expected if called after.

Is this behaviour described somewhere?

I am using OpenJDK 1.8.0_151.

Example:

import java.util.function.Supplier;
class Example {
  final String str;

  Supplier<Integer> test1 = () -> str.length();        // DOES NOT COMPILE
  Supplier<Integer> test2 = () -> this.str.length();   // DOES NOT COMPILE
  Supplier<Integer> test3 = () -> (this.str).length(); // DOES NOT COMPILE
  Supplier<Integer> test4 = () -> (this).str.length(); // OK

  Example(String str) {
    System.out.println(test4.get()); // NullPointerException
    this.str = str;
    System.out.println(test4.get()); // OK
  }
}

---

javac Example.java

Example.java:7: error: variable str might not have been initialized
Supplier<Integer> test1 = () -> str.length();        // DOES NOT COMPILE
                                ^
Example.java:8: error: variable str might not have been initialized
Supplier<Integer> test2 = () -> this.str.length();   // DOES NOT COMPILE
                                    ^
Example.java:9: error: variable str might not have been initialized
Supplier<Integer> test3 = () -> (this.str).length(); // DOES NOT COMPILE
                                     ^
3 errors
user2357112 supports Monica :

From JLS version 9, chapter 16:

Each local variable (§14.4) and every blank final field (§4.12.4, §8.3.1.2) must have a definitely assigned value when any access of its value occurs.

An access to its value consists of the simple name of the variable (or, for a field, the simple name of the field qualified by this) occurring anywhere in an expression except as the left-hand operand of the simple assignment operator = (§15.26.1).

str is the simple name of a final field, and this.str is the simple name of the field qualified by this. (this).str doesn't fall under either of those cases ((this) doesn't count as "qualified by this"), so it doesn't count as an access.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=438575&siteId=1