views:

249

answers:

7
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?

+5  A: 

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

Padmarag
Could you elaborate, *why* the compiler can't tell that? If the `if (a > 0)` is replaced with `if (1 > 0)`, it works.
Joonas Pulakka
That's just the rules laid out in the language specification, I'm afraid. A whole chapter is dedicated to this subject, and the rules are quite clear on when a variable is definitely assigned/not-assigned. Some may defy your intuition, but that's just the way the designers wanted it.
polygenelubricants
+2  A: 

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

codaddict
+3  A: 

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.

Joachim Sauer
+14  A: 

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.

polygenelubricants
instead of changing to `else`, one could also change `a` to `final` to make this code compile; the compiler will optimize the ifs away, effectively resulting in nothing else but `final int a = 1, b = 1;`
sfussenegger
A: 

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);
sfussenegger
+1  A: 

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.

medopal
+1  A: 

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

fastcodejava
More specifically, it _could_ be that smart through static analysis, but the Java spec is very strict and does not allow it in this case, according to @polygenelubricants.
Amigable Clark Kant
You are right, it could do that if it wanted to.
fastcodejava