// @skip-test
// To reproduce the problem, run:
// javac -processor nullness Issue556b.java
// java Issue556b
// and observe that the javac execution issues no warnings but the java
// execution suffers a null pointer exception.
// Before the constructor is invoked, static initializers and static blocks
// are executed. This suggests that the Initialization Checker can assume
// that static fields are initialized in the constructor.
//
// However, if any user-defined code -- including callbacks such as
// executions of equals() and hashCode() -- appears in a static initializer
// or static block, then static fields cannot be assumed to be
// initialized within the constructor.
public class Issue556b {
static class Parent {
private final Object o;
public Parent(final Object o) {
this.o = o;
}
@Override
public String toString() {
return o.toString();
}
}
static class Child extends Parent {
public static final Child CHILD = new Child();
private static final Object OBJ = new Object();
private Child() {
// This call should not be legal, because at the time that the
// call occurs, the static initializers of Child have not yet
// finished executing and therefore CHILD and OBJ are not
// necessarily initialized and are not necessarily non-null.
//:: error: (method.invocation.invalid)
super(OBJ);
}
}
static class Child2 extends Parent {
public static final Child2 CHILD;
private static final Object OBJ;
static {
CHILD = new Child2();
OBJ = new Object();
}
private Child2() {
// This call should not be legal, because at the time that the
// call occurs, the static initializers of Child have not yet
// finished executing and therefore CHILD and OBJ are not
// necessarily initialized and are not necessarily non-null.
//:: error: (method.invocation.invalid)
super(OBJ);
}
}
// Changing the order of the OBJ and CHILD fields prevents a null pointer
// exception.
static class ChildOk1 extends Parent {
private static final Object OBJ = new Object();
public static final Child CHILD = new Child();
private ChildOk1() {
// This call is legal, because OBJ is non-null at the time of the
// call. That's because OBJ is initialized before CHILD and
// therefore before the call to "new Child()".
super(OBJ);
}
}
// Changing the order of the OBJ and CHILD field assignments prevents a
// null pointer exception.
static class ChildOk2 extends Parent {
public static final ChildOk2 CHILD;
private static final Object OBJ;
static {
OBJ = new Object();
CHILD = new ChildOk2();
}
private ChildOk2() {
// This call is legal, because OBJ is non-null at the time of the
// call. That's because OBJ is initialized before CHILD and
// therefore before the call to "new Child()".
super(OBJ);
}
}
public static void main(final String[] args) {
System.out.println(Child.CHILD);
}
}