简体   繁体   中英

Why doesn't the java compiler recognise fields have been initialized?

Suppose I have the following piece of code

int myVar;
final boolean condition = <someCondition>;
if (condition) {
   myVar = 1;
}
if (condition) {
   System.out.println("myVar = " + myVar);
}

When I compiled this, I got the expected myVar might not have been initialized error. Is this a bug in the compiler? It's easy to see that "myVar" was set when condition is true, and it is only referenced when condition is true. ( condition is also never reset)

PS: To those comments on me needing to init it to 0, yes I am aware of that. But the point is, I wanted "myVar" to be final (ie., value set at most once)

The initialization requirement is a formal part of Java, as described in the JLS:

For every access of a local variable or blank final field x, x must be definitely assigned before the access, or a compile-time error occurs.

( JLS 8, chapter 16 ; emphasis in the original)

The JLS goes on to say

The analysis takes into account the structure of statements and expressions; it also provides a special treatment of the expression operators ! , && , || , and ? : ? : , and of boolean-valued constant expressions.

Except for the special treatment of the conditional boolean operators && , || , and ? : ? : and of boolean-valued constant expressions, the values of expressions are not taken into account in the flow analysis .

(emphasis added)

Note well that condition being final does not make it a "constant expression" as the specification defines that term. The specification goes on to give the specific rule for if statements :

V is [un]assigned after if (e) S iff V is [un]assigned after S and V is [un]assigned after e when [ e evaluates to] false .

In your particular code, then:

 int myVar; 

myVar is definitely un assigned here.

 final boolean condition = <someCondition>; if (condition) { myVar = 1; } 

myVar is "assigned after S" because S, the body of the if statement, performs an unconditional assignment. myVar is not assigned after evaluation of the condition, however, whether the condition evaluates to true or false . Therefore, myVar is not definitely assigned at this point in the method.

 if (condition) { 

And nothing has changed at this point: myVar still is not definitely assigned as far as the JLS rules are concerned, so its value must not be read. The compiler is therefore obligated to report an error in the next statement:

  System.out.println("myVar = " + myVar); } 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM