Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does if(Boolean.TRUE) {...} and if(true) {...} work differently in Java

Tags:

java

boolean

I want to know the difference between Boolean.TRUE and true values inside an if clause. Why does it give me a compilation error (that a value may not have been initialized) when I use Boolean.TRUE instead of true.

Below is my code :

public class Test {

    public void method1() {
        int x;
        if(Boolean.TRUE) {
            x = 200;
        }
        System.out.println("x: " + x);   // Compilation error       
    }

    public void method2() {
        int x;
        if(true) {
            x = 200;
        }
        System.out.println("x: " + x);   // Compiles fine
    }
}
like image 887
Ravi Jiyani Avatar asked Feb 16 '15 16:02

Ravi Jiyani


2 Answers

Short answer
For if (true) the compiler can deduce that x has been initialized before it's being read. This does not hold for the if (Boolean.TRUE) case.

Formal answer:
All local variables must have a definite assignment before being read (14.4.2. Execution of Local Variable Declarations):

[...] If a declarator does not have an initialization expression, then every reference to the variable must be preceded by execution of an assignment to the variable, or a compile-time error occurs by the rules of §16.

In this case there's an if statement involved in the code preceding the reference to the variable, so the compiler performs some flow analysis. However, as spelled out in Chapter 16. Definite Assignment:

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.

So since true is a boolean-valued constant expression and Boolean.TRUE (which is a reference to a value on the heap, subject to auto-unboxing etc) is not it follows that

if (true) {
    x = 200;
}

yields a definite assignment of x while

if (Boolean.TRUE) {
    x = 200;
}

does not.

like image 131
aioobe Avatar answered Oct 21 '22 02:10

aioobe


The difference exists because one is a true constant while the other is just mimicking one.

The compiler will look at things like if statements and try to figure out whether they will always be a given expression (== true, == false, == null, etc) but it will only do this up to a certain level.

In the case of true there is no ambiguity: it will always undoubtedly represent "true". However Boolean.TRUE is just a field, which is apparently not as far as the compiler is willing to go.

public static final Boolean TRUE = new Boolean(true);

Think for example about what would be done if reflection is involved.

You can see this clearly when you introduce an extra level of complexity:

public static void main(String[] args) {
    int x;
    if(getCondition()) {
        x = 5;
    }
    System.out.println(x);
} 

private static boolean getCondition(){
    return true;
}

Even though the expression will always be true, the compiler still complains that x might be unassigned. Only the most rudimentary verification is done to help you.

like image 41
Jeroen Vannevel Avatar answered Oct 21 '22 03:10

Jeroen Vannevel