6

A curiosity that I've just noticed, rather than a problem.

I'm not allowed to write

public boolean x() {
  return null;
}

or this:

public boolean x() {
  if (DEBUG) {
    return true;
  } else {
    return null;
  }
}

but I am allowed to write

public boolean x() {
  return DEBUG ? true : null;
}

Why is this? (It appears to throw an NPE if the "else" branch is taken.)

Purag
  • 16,941
  • 4
  • 54
  • 75
Michael Kay
  • 156,231
  • 11
  • 92
  • 164
  • Thanks @Thilo. To clarify: the question is, why isn't the ternary construct rejected in the same way as the other two examples? – Michael Kay Aug 28 '15 at 08:00
  • 1
    @MichaelKay Again, just out of curosity, have you tried `public boolean x() { if (DEBUG) { return true; } return null; }` ? – Sudhansu Choudhary Aug 28 '15 at 08:01
  • possible dupplicate http://stackoverflow.com/questions/978324/java-ternary-immediate-if-evaluation ? – Jens Aug 28 '15 at 08:02
  • in java8 it's even more complicated. see https://groups.google.com/forum/#!topic/java-lang-fans/-ap9v5MDO_4 – ZhongYu Aug 28 '15 at 08:38

3 Answers3

10

As the jls states:

The type of a conditional expression is determined as follows: If the second and third operands have the same type (which may be the null type), then that is the type of the conditional expression. If one of the second and third operands is of primitive type T, and the type of the other is the result of applying boxing conversion (§5.1.7) to T, then the type of the conditional expression is T.

This means java allows null, since it can be used to generate an instance of Boolean, which can be unboxed to boolean (read the section about boxing in the jls for more info). But since the Boolean instance is initialized null, the call to booleanValue() will result in a NullPointerException.

2

The ternary operator sees that you have the two options true and null, so it has to use autoboxing and type itself (i.e. the result of the conditional operator) as Boolean (which in turn gets unboxed again automatically by the return).

The exact rules are a bit complicated, you can find them in the JLS

At run-time you then get a NullPointerException during the unboxing of the return value.

Thilo
  • 257,207
  • 101
  • 511
  • 656
0

See JLS-15.25

The type of a conditional expression is determined as follows: ... If one of the second and third operands is of the null type and the type of the other is a reference type, then the type of the conditional expression is that reference type.

...

At run time, the first operand expression of the conditional expression is evaluated first. If necessary, unboxing conversion is performed on the result.

The resulting boolean value is then used to choose either the second or the third operand expression:

...

The chosen operand expression is then evaluated and the resulting value is converted to the type of the conditional expression as determined by the rules stated above.

This conversion may include boxing (§5.1.7) or unboxing (§5.1.8) conversion.

So - essentially - your null is boxed into a Boolean.

Community
  • 1
  • 1
OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
  • But the other is not a reference type. Read on in the JLS for the rule that applies here. – Thilo Aug 28 '15 at 08:07