12

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
    }
}
Raedwald
  • 46,613
  • 43
  • 151
  • 237
Ravi Jiyani
  • 919
  • 1
  • 10
  • 26
  • 1
    This makes no sense. What's the point of checking if true is true? – Lawrence Aiello Feb 16 '15 at 16:49
  • 3
    @LawrenceAiello: you're missing the point of the question. In one case the compiler can correctly identify the expression is always true, in the other it can't. – Jeroen Vannevel Feb 16 '15 at 16:51
  • 4
    It throws an error, but that is "value x may not have been initialized". And that's because behind Boolean.TRUE there could also hide 'false'. – Marco Feb 16 '15 at 16:52
  • 1
    See also http://stackoverflow.com/questions/4894311/what-is-the-difference-between-boolean-true-and-true-in-java – Raedwald Feb 21 '15 at 08:55

3 Answers3

10

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.

aioobe
  • 413,195
  • 112
  • 811
  • 826
5

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.

Jeroen Vannevel
  • 43,651
  • 22
  • 107
  • 170
1

It does throw this error because it does not know what hides behind Boolean.TRUE. TRUE is a static field of the type boolean in the class Boolean, but its value could also be false. It isn't obviously, 'though.

Marco
  • 330
  • 3
  • 12