Java boolean and null strangeness

148 Views Asked by At

Could anyone please helpe me in understanding why my code could generate the following output?

Please note, that f is here for debug purpose, f[0]=(lastLine!=null) is just an equivalent to lastLine!=null test, so it is not the bug.

boolean f[] = new boolean[6];
if (f[0]=(lastLine!=null) // есть следующая строка
    || (f[1]=isEdgeTime) // конец сессии 
    || (f[2]=td.getHour() <10) // или уже утро, после полуночи все свечки хороши
    || (f[3]=(td.getHour() == 23 && td.getMinute() >=50))
    || (f[4]=currServerHour > lineHour) // или час сменился
    || (f[5]=currServerMinutesPeriod > linesMinutesPeriod)
){
    answer.append(classCode).append(".")
          .append(TickerUtils.getRoot(ticker))
          .append(";").append(minutes).append(";")
          .append(line)
          .append("\n");
    System.out.println(Arrays.toString(f));
    if (f[0])
        System.out.printf("\"%s\" : %d, currServerMinute=%d; %d > %d\n", lastLine, (lastLine!=null? 1: 0), currServerMinute, currServerMinutesPeriod, linesMinutesPeriod);
    line = lastLine;
} 

output:

[true, false, false, false, false, true]
"null" : 0, currServerMinute=50; 10 > 9

that I can't understand is why "lastLine" is not null, as f[0] is true and at the same time lastLine != null gives me false, so it is null, actually, how this could be?

3

There are 3 best solutions below

1
On BEST ANSWER

If looks like you are assigning to f[0] the following :

(lastLine!=null) // есть следующая строка
|| (f[1]=isEdgeTime) // конец сессии 
|| (f[2]=td.getHour() <10) // или уже утро, после полуночи все свечки хороши
|| (f[3]=(td.getHour() == 23 && td.getMinute() >=50))
|| (f[4]=currServerHour > lineHour) // или час сменился
|| (f[5]=currServerMinutesPeriod > linesMinutesPeriod)

Therefore f[0] can be true even though lastLine is null.

Try to change your condition to:

if ((f[0]=(lastLine!=null)) // есть следующая строка
    || (f[1]=isEdgeTime) // конец сессии 
    || (f[2]=td.getHour() <10) // или уже утро, после полуночи все свечки хороши
    || (f[3]=(td.getHour() == 23 && td.getMinute() >=50))
    || (f[4]=currServerHour > lineHour) // или час сменился
    || (f[5]=currServerMinutesPeriod > linesMinutesPeriod)
)

if you want f[0] to contain the value of (lastLine!=null).

This will take care of the value of f[0]. However, if f[i] is true for any i, f[i+1] won't be evaluated due to short circuit evaluation of the || condition, so you'll always have at most one true value in the f array. I'm not sure if that's what you want.

0
On

You should read up on operator precedence in Java: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html

Specifically, in your code, f[0] isn't assigned just the result of (lastLine!=null), but the entire boolean expression, as the OR operator || has precedence over the assignment operator =. So your first line is equivalent to (I added parentheses to make the operator precedence explicit):

if (f[0]=((lastLine!=null) // есть следующая строка
  || (f[1]=isEdgeTime) // конец сессии 
  || (f[2]=td.getHour() <10) // или уже утро, после полуночи все свечки хороши
  || (f[3]=(td.getHour() == 23 && td.getMinute() >=50))
  || (f[4]=currServerHour > lineHour) // или час сменился
  || (f[5]=currServerMinutesPeriod > linesMinutesPeriod)
)){

But general advice: NEVER use the result of an assignment in a test. Yes, it's legal Java, but it's bad style because it can get confusing very quickly, as you found out. Remember, code is written once but read many times, so it's important for it to be clear to the next person reading it.

0
On

try to do the assignments outside of an if statement. The reason this might make a change is because we know that the if statement will exit on the first true condition. It is possible that the compiler and/or runtime interpretaer rearrenges the if statement for performance (i.e. branch predition) considerations.