FULL PRODUCT VERSION :
not important
ADDITIONAL OS VERSION INFORMATION :
not important
EXTRA RELEVANT SYSTEM CONFIGURATION :
not important
A DESCRIPTION OF THE PROBLEM :
package net.octoplar;
/**
* Created by Octoplar on 05.10.2016.
*/
//This program output is
//1
//1
//2
class C {
static final int i=C.j+C.k; // "static field that are constant variable" k have default initial value here. This is JLS violation
static final int j=1;
static final int k=i+j;
public static void main(String[] args) {
System.out.println(i); //1
System.out.println(j); //1
System.out.println(k); //2
}
}
/*https://docs.oracle.com/javase/specs/jls/se8/html/ */
/*According point 15.28
* expression 'C.j+C.k' is constant expression, because it composed using:
* C.j - Qualified names (��6.5.6.2) of the form TypeName . Identifier that refer to constant variables (��4.12.4).
* + - The additive operators + and - (��15.18)
* C.k - Qualified names (��6.5.6.2) of the form TypeName . Identifier that refer to constant variables (��4.12.4).
*
* expression '1' is constant expression, because it composed using:
* 1 - Literals of primitive type and literals of type String (��3.10.1, ��3.10.2, ��3.10.3, ��3.10.4, ��3.10.5)
*
* expression 'i+j' is constant expression, because it composed using:
* i - Simple names (��6.5.6.1) that refer to constant variables (��4.12.4).
* + - The additive operators + and - (��15.18)
* j - Simple names (��6.5.6.1) that refer to constant variables (��4.12.4).
*
* According point 4.12.4
* i, j, k is constant variables
* A constant variable is a final variable of primitive type or type String that is initialized with a constant expression (��15.28).
* Whether a variable is a constant variable or not may have implications with respect to class initialization (��12.4.1),
* binary compatibility (��13.1, ��13.4.9), and definite assignment (��16 (Definite Assignment)).
*
*
*
* According point 8.3.2
* i, j, k is static fields that are constant variables
* Note that static fields that are constant variables (��4.12.4) are initialized before other static fields (��12.4.2).
* This also applies in interfaces (��9.3.1).
* Such fields will never be observed to have their default initial values (��4.12.5), even by devious programs.
*
* But in this example program observe k(static field that are constant variable) in two states:
* default initial value 0 at "static final int i=C.j+C.k;"
* and initial value 2 at "System.out.println(k);"
* */
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run this:
class C {
static final int i=C.j+C.k; // "static field that are constant variable" k have default initial value here. This is JLS violation
static final int j=1;
static final int k=i+j;
public static void main(String[] args) {
System.out.println(i); //1
System.out.println(j); //1
System.out.println(k); //2
}
}
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I expect no results.
I learn JLS now and i find this bug.
ACTUAL -
1
1
2
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
class C {
static final int i=C.j+C.k; // "static field that are constant variable" k have default initial value here. This is JLS violation
static final int j=1;
static final int k=i+j;
public static void main(String[] args) {
System.out.println(i); //1
System.out.println(j); //1
System.out.println(k); //2
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
1. remove from JLS 8.3.2 words "Such fields will never be observed to have their default initial values (��4.12.5), even by devious programs." because it is not true.
2. Forbid all types forward references during field initialization. Now forbidden ornly direct forwadr reference. Example:
class B {
//Instance variable forward reference example
int iv1= iv; // error. Illegal forward reference
int iv2=this.iv; //this is too forward reference, but all OK
B selfRef=this;
int iv3=selfRef.iv; //this is too forward reference, but all OK
//Class variable forward reference example
static int cv1 =cv; //error. Illegal forward reference
static int cv2 =B.cv; //this is too forward reference, but all OK
int iv =11;
static int cv=22;
}