JDK-6514490 : 12.5: Request to execute final field initializers before superclass construction
  • Type: Enhancement
  • Component: specification
  • Sub-Component: language
  • Affected Version: 6
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • Submitted: 2007-01-18
  • Updated: 2014-04-10
  • Resolved: 2014-04-10
Related Reports
Relates :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
>javac -version
javac 1.6.0

>java -version
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Windows XP

A DESCRIPTION OF THE PROBLEM :
JLS Chapter 16, first paragraph: "Each local variable (��14.4) and every blank final (��4.12.4) field (��8.3.1.2) must have a definitely assigned value when any access of its value occurs. "

The code below throws a null pointer exception because a final field is read before being assigned.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run code below

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
For the program to exit normally.

ACTUAL -
Null pointer exception

ERROR MESSAGES/STACK TRACES THAT OCCUR :
>java ndafinal
Exception in thread "main" java.lang.NullPointerException
        at B.f(ndafinal.java:15)
        at A.<init>(ndafinal.java:9)
        at B.<init>(ndafinal.java:13)
        at ndafinal.main(ndafinal.java:4)

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
class ndafinal {
  public static void main(String[] args) {
    // causes null pointer error
    new B();
  }
}

class A {
  A() { f(); }
  int f() { return 0; }
}

class B extends A {
  private final Object o = new Object();
  int f() { return o.hashCode(); }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
In more complex applications, it becomes necessary to check if a final field is not null before relying on its value, partly defeating the point of the "final" keyword.

IMO either final fields should be assigned before the super constructor is called, or the JLS should be clarified to indicate that access of an unassigned final field is possible and has a definate value (i.e. null).

Comments
Definite assignment analysis in JLS16 concerns *blank* final fields, which B.o isn't. As you say, "access of an unassigned final field is possible" because B.o's initializer has not been executed when A's constructor runs - but while B.o may be unassigned at that point, it is not *definitely* unassigned by JLS16's analysis. What this request wants is an analysis that applies to non-blank final fields and would consider a class's known hierarchy. The analysis for [un]assignment (not just *definite* [un]assignment) of B.o would inspect A's instance initializers and constructors. This is entirely new and not something I see happening soon. (It is related to once-only code, 4492260). I would prefer a general language feature to help avoid NPEs. Executing the instance initializers of final fields before a super() invocation is a big change and will not happen. An instance initializer can depend on non-final instance variables, so their instance initializers would have to be run too; now it's not immediately obvious which fields are assigned before the superclass's constructor is run and which aren't. Also, a field's instance initializer can use inherited fields which, if we haven't initialized the superclass instance with super() yet, won't be assigned.
10-04-2014