Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 supplier behaviour: final variable might not be initialized

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
like image 969
kristjank Avatar asked Mar 05 '18 20:03

kristjank


People also ask

Can final variables not be initialized?

A final variable can only be initialized once, either via an initializer or an assignment statement. It does not need to be initialized at the point of declaration: this is called a "blank final" variable.

What does it mean if a variable has not been initialized in Java?

Initializing a variable means specifying an initial value to assign to it (i.e., before it is used at all). Notice that a variable that is not initialized does not have a defined value, hence it cannot be used until it is assigned such a value.

How do you declare a final variable in Java without initializing?

Declaring final variable without initialization If you declare a final variable later on you cannot modify or, assign values to it. Moreover, like instance variables, final variables will not be initialized with default values. Therefore, it is mandatory to initialize final variables once you declare them.

Can a final variable be initialized in constructor?

A blank final variable can be initialized inside an instance-initializer block or inside the constructor. If you have more than one constructor in your class then it must be initialized in all of them, otherwise, a compile-time error will be thrown.


1 Answers

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.

like image 114
user2357112 supports Monica Avatar answered Oct 18 '22 01:10

user2357112 supports Monica