2

Here is a little oddity:

Integer oddity(boolean b1, boolean b2) {
  return b1 ? 0 : b2 ? 1 : null;
}

This will fail with a NullPointerException if b1 and b2 are false. But this:

Integer oddity(boolean b1) {
  return b1 ? 0 : null;
}

Does not throw an NPE when b1 is false.

Why is this?

Andy Turner
  • 137,514
  • 11
  • 162
  • 243

1 Answers1

2

As you might imagine, the NullPointerException in the first case is as a result of implicit unboxing. This is all as described in JLS Sec 15.25; but the rules are complex, and have some tricky facets.

The surprising thing here is that this:

System.out.println(b ? 0 : null);

Is not the same as

Integer v = null;
System.out.println(b ? 0 : v);
  • The conditional expression in the first case has type Integer: the 0 is boxed to Integer.valueOf(0). Hence, this statement will complete normally, printing 0 or null.
  • The conditional expression in the second case has type int: v is unboxed to v.intValue(). Hence, this statement will either print 0, or fail with a NullPointerException.

So: the first example in the question is actually a combination of these two cases. Inserting the implicit boxing and unboxing, it becomes:

return Integer.valueOf(b1 ? 0 : (b2 ? Integer.valueOf(1) : null).intValue());

which can fail on the call to intValue(); whereas the second example in the question is:

return b1 ? Integer.valueOf(0) : null;

which will not fail.


If you want to return 0, 1 or null, the smallest change would be to box the 0 explicitly:

return b1 ? Integer.valueOf(0) : b2 ? 1 : null;

This looks awkward, because the 0 and 1 are differently represented. You could box the 1 explicitly too:

return b1 ? Integer.valueOf(0) : b2 ? Integer.valueOf(1) : null;

which works, but is verbose, and some well-meaning colleague (or you, when you come back to it some months later, having forgotten the reasons for the explicit boxing) will remove the boxing, because you don't need that, right?

Personally - having spent time recently looking at the conditional operator in some detail - I would opt to avoid it completely, and not risk falling foul of its curious type rules.

if (b1) {
  return 0;
} else if (b2) {
  return 1;
} else {
  return null;
}
Andy Turner
  • 137,514
  • 11
  • 162
  • 243