Search code examples
javainitialization

Why is x not initialized in this?


Why is x not initialized in the following ?

public class rough {
    public static void main(String[] args) {
        int x;
        boolean found = false;
        for (int i = 0; i < 10; i++) {
            if (Math.random() < 0.5) {
                found = true;
                x = 10;
                break;
            }

        }
        if (!found)
            x = -1;
        System.out.println(x);//x isn't initialized here
    }
}

On average, for half of the iterations, the if inside the for loop would be true, thus initializing x. For the other half, found stays false therefore the outer if would initialize. Therefore, I don't understand why the compiler is annoyed.

As the ultimate distillation (see successive simplifications below), consider

public static void main(String[] args) {
        int x;
        boolean found = false;
        if (!found)
            x = -1;

        System.out.println(x);
    }

which also gives the error that x isn't init.

previous simplifications

Even more surprisingly, changing if (Math.random() < 0.5) to if(true) also has the same problem.

In fact, investigating further, replacing the original for loop by these

        for (int i=0;i<1;i++)
           x = 10;
 for (; !found; ) {
            x = 10;
            break;
        }

is equally worse. Only for(;;){... break;} & for(;true;){... break;} don't raise any init. errors.


Solution

  • (Writing this up as a separate answer since I think it'll benefit from being taken out of comments).

    This is the language-lawyer's answer.

    The language specification requires initialization of variables before they are used.

    The rules include:

    1. The variable must be given a value on all possible paths through the code. The specification refers to this as 'definite assignment'.

    2. The compiler does not consider the values of expressions in this analysis. See Example 16.2 for this.

    The second rule explains why even in cases that are 'obvious' to us, the compiler can't use that knowledge. Even if the compiler-writer cared to do a deeper analysis, adherence to the Java specification forbids it.

    If the next question is 'but why?' then I'd have to guess, but the point of a standard is to get consistent behaviour. You don't want one compiler accepting as legal Java something that another compiler rejects.