Why does the Java compiler complain about a local

2019-07-03 14:58发布

问题:

int a = 1, b;
if(a > 0) b = 1;
if(a <= 0) b = 2;
System.out.println(b);

If I run this, I receive:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
 The local variable b may not have been initialized

 at Broom.main(Broom.java:9)

I know that the local variables are not initialized and is your duty to do this, but in this case, the first if doesn't initialize the variable?

回答1:

If you change the second if to else, then the compiler would be happy.

int a = 1, b;
if(a > 0) b = 1;
else b = 2;
System.out.println(b);

If you really want to go deep into this matter, one whole chapter of the Java Language Specification is dedicated to the issue of Definite Assignment. This case pertains to your specific example:

the rules do not accept the variation:

void flow(boolean flag) {
        int k;
        if (flag)
                k = 3;
        if (!flag)
                k = 4;
        System.out.println(k);  // k is not "definitely assigned" before here
}

and so compiling this program must cause a compile-time error to occur.

This particular example (and many other illustrative ones) may seem to defy your expectation, but this is exactly the way the language designers wanted it, and all compilers must abide by the rules.



回答2:

Focus on "IF", The compiler can't tell if the condition will be true.



回答3:

Please don't try to run your code when it doesn't even compile.

Usually you couldn't do that anyway, but modern IDEs are so "helpful" to allow you to do that. They usually replace uncompilable parts of the code with code that just throws an error such as the one you see.

The much better approach is to look at the error messages your compiler/IDE gives you and try to fix those before you try to run your application.

Learning the difference between compiler errors and runtime exceptions is an important step to take.



回答4:

In Java a local variable must be initialized before its used.

In your case both the initializations are conditional and the compiler cannot determine if any of the conditionals will be true. This upsets the compiler.

From Java docs:

A local variable (§14.4, §14.13) must be explicitly given a value before it is used, by either initialization (§14.4) or assignment (§15.26), in a way that can be verified by the compiler using the rules for definite assignment



回答5:

Local variables are not replaced in compile time so the compiler have no idea if the IF is true or false.

On the other hand if the variable was defined final then it will be replaced during compile time.



回答6:

Java compiler cannot find out that the other if works as an else. Compilers are smart but not that smart.



回答7:

You could add the final keyword to the declaration of a to help your compiler optimizing the code.

// this compiles just fine
final int a = 1, b;
if(a > 0) b = 1;
if(a <= 0) b = 2;
System.out.println(b);