Java compiler throws 'might not have been initialized' error incorrectly?

Advertisements

Here’s a sample method:

boolean method(int value, boolean check1, boolean check2) {
    String code;
    boolean valueIncorrect = false;
    boolean otherIncorrect = false;

    if (value < 0 || value > 10) {
        code = "lengthCode";
        valueIncorrect = true;
    }
    if (check1) {
        code = "otherCode";
        otherIncorrect = true;
    } else if (check2) {
        code = "otherCode";
        otherIncorrect = true;
    }

    if(!valueIncorrect && !otherIncorrect) {
        return true;
    }
    
    if (otherIncorrect) {
        return code.contains("HELLO");
    }
    return true;
}

When I try to compile, I get the error: variable code might not have been initialized at the line where I try to call the contains() method.
If we look at the logic, it’s impossible for code to be null at that point, right? Or am I tripping? Execution will only reach that point if one of the booleans is true, and wherever either of them is being set to true, the value of code is also being set.
So I don’t expect an infinitely complex level of analysis by the compiler, but I also know that if it was a much simpler condition:

if(boolean) code = "x";
else code = "y";
return code.contains("whatever");

like this would not throw an error. What am I misunderstanding?

>Solution :

You are assuming that since you can infer that code will always be initialized, the Java compiler can (and should) make the same inferences and call your code correct.

In fact, the compiler is applying the definite assignment rules set out in the JLS rules in the 16: Definite Assignment chapter. These rules do not allow (for example) the values of conditions to be taken into account unless they are (compile time) constant expressions … in the sense defined by the JLS.

A conformant compiler is required to implement those rules literally. It is not acceptable for a clever Java compiler to (say) use the latest machine reasoning technology and deduce that code will in fact always be initialized before use.

Why? Because that leads to portability problems; i.e. one Java compiler calls your source code erroneous and another one says it is correct.


In short, it is not a Java compiler error. It is a feature of the Java language.

Leave a ReplyCancel reply