-
Bug
-
Resolution: Fixed
-
P4
-
8, 9
-
b120
-
generic
-
generic
-
Verified
FULL PRODUCT VERSION :
java version "1.8.0_74"
Java(TM) SE Runtime Environment (build 1.8.0_74-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.74-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]
A DESCRIPTION OF THE PROBLEM :
There is a subtle change in JLS Chapter 16 regarding access of final fields:
Java 6 JLS has:
"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. An access to its value consists of the simple name of the variable occurring anywhere in an expression except as the left-hand operand of the simple assignment operator =."
In Java 7 and later:
"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)."
There is an inconsistency in how javac handles this.
Take this class for example:
public class Unassigned {
public final int a;
public int b;
Unassigned(int value) {
b = this.a;
a = value;
}
}
Here, javac correctly reports a problem:
Unassigned.java:6: error: variable a might not have been initialized
b = this.a;
^
1 error
However, by changing the code slightly:
public class Unassigned {
public final int a;
public int b;
Unassigned(int value) {
b = (this).a;
a = value;
}
}
...javac now accepts the code.
The JLS has, in Chapter 15.8.5:
"In particular, the presence or absence of parentheses around an expression does not (except for the case noted above) affect in any way /.../ whether a variable is definitely assigned, definitely assigned when true, definitely assigned when false, definitely unassigned, definitely unassigned when true, or definitely unassigned when false (§16 (Definite Assignment))."
So, this appears to be a compiler bug.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile example code below with javac.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Compilation should fail like this:
Unassigned.java:6: error: variable a might not have been initialized
b = (this).a;
^
1 error
ACTUAL -
Compilation succeeds.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
public class Unassigned {
public final int a;
public int b;
Unassigned(int value) {
b = (this).a;
a = value;
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Remove parentheses around "this".
java version "1.8.0_74"
Java(TM) SE Runtime Environment (build 1.8.0_74-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.74-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]
A DESCRIPTION OF THE PROBLEM :
There is a subtle change in JLS Chapter 16 regarding access of final fields:
Java 6 JLS has:
"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. An access to its value consists of the simple name of the variable occurring anywhere in an expression except as the left-hand operand of the simple assignment operator =."
In Java 7 and later:
"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)."
There is an inconsistency in how javac handles this.
Take this class for example:
public class Unassigned {
public final int a;
public int b;
Unassigned(int value) {
b = this.a;
a = value;
}
}
Here, javac correctly reports a problem:
Unassigned.java:6: error: variable a might not have been initialized
b = this.a;
^
1 error
However, by changing the code slightly:
public class Unassigned {
public final int a;
public int b;
Unassigned(int value) {
b = (this).a;
a = value;
}
}
...javac now accepts the code.
The JLS has, in Chapter 15.8.5:
"In particular, the presence or absence of parentheses around an expression does not (except for the case noted above) affect in any way /.../ whether a variable is definitely assigned, definitely assigned when true, definitely assigned when false, definitely unassigned, definitely unassigned when true, or definitely unassigned when false (§16 (Definite Assignment))."
So, this appears to be a compiler bug.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile example code below with javac.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Compilation should fail like this:
Unassigned.java:6: error: variable a might not have been initialized
b = (this).a;
^
1 error
ACTUAL -
Compilation succeeds.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
public class Unassigned {
public final int a;
public int b;
Unassigned(int value) {
b = (this).a;
a = value;
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Remove parentheses around "this".
- relates to
-
JDK-8204610 Compiler confused by parenthesized "this" in final fields assignments
- Resolved