1

Why is the compiler is happy that variable g is initialized in if(true) statement while complains regarding g initialization in if(gg) case, throwing the following error:

Error:(11, 28) java: variable g might not have been initialized

  public static void main(String args[]) {
    boolean gg = true;
    int g;
    if (gg)
    //  if (true)
    {
        g = 6;
    }
    System.out.println(g);
}
0xadecimal
  • 696
  • 5
  • 18
vico
  • 17,051
  • 45
  • 159
  • 315
  • `gg` is not a *compile-time constant*, so compiler doesn't know that `gg` is `true`. The rules for determining if `g` is *definitely-assigned* in the `print` statement are well-documented, and takes up an entire chapter in the [Java Language Specification](https://docs.oracle.com/javase/specs/jls/se13/html/jls-16.html). – Andreas Oct 09 '19 at 11:59
  • Compiler can't be sure gg is always true (it can reassign somewhere in code), there are couple of answers in site – Ori Marko Oct 09 '19 at 11:59
  • Because the compiler doesn't keep a state, so that it knows if gg is always going to be true. It sees that you have a Boolean and that it may be false in some cases (otherwise why would you have an if statement?). If gg is false, then g will be uninitialized and your `System.out.print()` statement will produce an error – Soutzikevich Oct 09 '19 at 12:20
  • See https://stackoverflow.com/questions/9082971/compile-time-constants-and-variables – Raedwald Oct 09 '19 at 12:22

3 Answers3

0

true is a constant expression, the compiler can deduct its value compile time.

On the other hand, gg is not constant, but a variable, that you could initialize with anything (even an expression, a return value of a function, etc). So, the compiler does not check how did you initialize that variable, is assumes that it can be anything.

That's why the compiler thinks that the variable g can or cannot be initialized.

How deep do you think the compiler can go? Take this one, for example:

boolean gg = Math.random() >= 0.5;
gg = gg ? gg : true;

We know that gg will be true, but how does the compiler know it?

Or another example:

boolean gg = (Math.random() >= 0.0);

Again, we know that it is always true (because random() is between 0.0 and 1.0), but the compiler doesn't know.

So, it's not an easy task for a compiler to do, therefore the compiler creators decided to check only the constant expressions when predicting execution flow, and not to guess the variable values.

That's the reason why you get a warning in one case and don't in the other.

gaborsch
  • 15,408
  • 6
  • 37
  • 48
0

This is due to the difference between declaration and initialisation.

The part before the equals sign is the declaration boolean gg or int g and the initialisation is the = true.

In the case above, gg is always initialised but g is only initialised if gg is true. This can only be known by running the code to determine gg's value (we can tell it's true by running through the code manually), hence we get a complaint from the compiler the g variable may not be initialised.

silleknarf
  • 1,219
  • 6
  • 22
0

The compiler will most likely optimize your if (true) condition to no condition at all (try and de-compile your .class, you should see the if block gone).

However, it is not as foreseeing when it comes to even local variable references with no possible changes within context, so it won't "optimize" for that, a sign that it will not predict that your condition will always be true.

As such it leaves you with a local variable initialized only at a condition (regardless of how factually that condition can only be true at runtime in this specific context), and referenced later by your println invocation, with the "risk" of not actually having been initialized.

That in turn, causes the "eager" compiler error.

Mena
  • 47,782
  • 11
  • 87
  • 106