0

Consider body of a class which has only these methods:

Integer getA()
{
    return 0;
}

Integer getB()
{
    return 1;
}

void testJava1()
{
    final Integer a1, b1;
    if ((a1 = getA()) != null && (b1 = getB()) != null)
    {
        System.out.println(a1 + " and " + b1); // fine
    }
}

void testJava2()
{
    final Integer a1, b1;
    final boolean condition = ((a1 = getA()) != null) && ((b1 = getB()) != null);
    if (condition)
    {
        System.out.println(a1 + " and " + b1); // variable might have been not initialized???
    }
}

void testJava3()
{
    final Integer a1, b1;
    final boolean conditionA = (a1 = getA()) != null;
    final boolean conditionB = (b1 = getB()) != null;
    if (conditionA && conditionB)
    {
        System.out.println(a1 + " and " + b1); // fine
    }
}

void testJava4()
{
    final Integer a1, b1;
    final boolean conditionA = (a1 = getA()) != null;
    final boolean conditionB = (b1 = getB()) != null;
    final boolean conditionC = conditionA && conditionB;
    if (conditionC)
    {
        System.out.println(a1 + " and " + b1); // fine
    }
}

Why does testJava2 fail to compile? The compiler reports

variable might not have been initialized

The condition will be false if b1 was null, so b1 would never be accessed within the if block. Why isn't the compiler smart enough to detect that?

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
Michael P
  • 670
  • 7
  • 23
  • 1
    If the first condition fails, the second will never execute. And that is why b1 might not have been initialized – ControlAltDel Feb 10 '17 at 15:38
  • Why do you want to do something like this anyway? – EJoshuaS - Stand with Ukraine Feb 10 '17 at 15:41
  • 1
    @Sotirios Delimanolis I think that the problem is not only related with shortcircuiting but also to the fact that the compiler doesn't try to be too clever and don't associate nested computations performed for an instruction with an unrelated instruction. – davidxxx Feb 10 '17 at 16:02
  • @davidxxx I don't get what you're trying to say. This is related to [_definite assignment_](http://docs.oracle.com/javase/specs/jls/se8/html/jls-16.html#jls-16.1.2) exactly because of the short circuiting. I don't know what's not _too clever_, this is how the language is designed. – Sotirios Delimanolis Feb 10 '17 at 17:11
  • @Sotirios Delimanolis In the page you refer to, please look at "Example 16-2. Definite Assignment Does Not Consider Values of Expressions". The example illustrate in a some way what I called in my comment : "the compiler doesn't associate nested computations performed for an instruction with an unrelated instruction" – davidxxx Feb 10 '17 at 17:51
  • @davidxxx You mean the return values of `getA` and `getB`? The JLS also talks about that in the end of that example, concerning constant expressions. You can't expect a runtime to potentially recur through method invocations to see what results are possible. The Java folks decided to set the limit at constant expressions. You think that warrants reopening? You think _that's_ their misunderstanding? – Sotirios Delimanolis Feb 10 '17 at 18:01
  • 1
    @Sotirios Delimanolis The problem is not so far. but it concerns : `final boolean condition = ((a1 = getA()) != null) && ((b1 = getB()) != null);` in the `testJava2()` method. `((a1 = getA()) != null) && ((b1 = getB()) != null);` is not a constant expression. So `b1` is considered as not initialized by the compiler in any case even if we know that if when condition is `true` it means both `a1` and `b1` are initialized. – davidxxx Feb 10 '17 at 18:24
  • 1
    The main purpose of my question is to point, that the same expression moved to the final variable before "if" is considered by the compiler as leaving b1 uninitialized. But dividing this expression into two logically exact expressions makes compiler thinking that b1 is properly initialized again. I do not know exactly JLS statements, but it is strange to me, that testJava3, and testJava4 are fine. – Michael P Feb 11 '17 at 20:11
  • 1
    @SotiriosDelimanolis I can understand that this is related with short circuiting, but I see it other way: if the first part of this expression (in testJava2) is short circuited because of false result, then there is no need to touch b1, and the whole condition is false, so the conditional code block will not execute and there is no need to touch b1 in any way too. This is clearly visible in testJava1 - why expression rules changes inside "if"? – Michael P Feb 11 '17 at 20:25

0 Answers0