4

Given the following code:

boolean c = true;
boolean d = true;
boolean b = c ? null : d;

System.out.println(b);

Why does the compiler not complain here? Variable b is a primitive datatype, shouldn't the null produce an error message like "Type mismatch: cannot convert from null to boolean"?

My best guess is, that there's some autoboxing going on? I saw this code in a project, but I would love to know the exact reason behind this...

EDIT1: As noted below by Mena, this code produces a NullPointer during runtime

EDIT 2: the following form also compiles without error:

boolean c = false;
boolean d = true;
boolean b = c ? null : d;

System.out.println(b);

EDIT 3: When trying to compile with compiler level 1.4, this will NOT compile, but produce an error:

Incompatible conditional operand types null and boolean.

So auto-boxing would make sense, as it was introduced with 1.5?

zeisi
  • 5,520
  • 2
  • 22
  • 21

3 Answers3

1

The expression on the RHS is of type Boolean and will be auto-unboxed at runtime; compile time type checking won't be affected. The unboxing will lead to a runtime exception.

OhleC
  • 2,821
  • 16
  • 29
  • 1
    that was my thought too. could you provide a source for your answer? would like to better understand why this is happening – zeisi Sep 10 '18 at 12:35
  • @zeisi https://docs.oracle.com/javase/specs/jls/se10/html/jls-15.html#jls-15.25.1 – user1803551 Sep 10 '18 at 12:39
  • It's generally always legal to assign an expression of a boxed type to a primitive variable (see [here](https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html) for example. The compiler cannot do a null check of arbitrary expressions. – OhleC Sep 10 '18 at 12:40
0

This does not compile, since we can not assign the null value to a variable of primitive type

boolean e = null;

This also does not compile, although there is a decision, the compiler detects that the value is always null and the same as the previous case

boolean f = c ? null : null;

In this case, as the compiler does not know the final value of b then the code compiles, but fails to run because finally the value is null

boolean c = true;
boolean d = true;
boolean b = c ? null : d;
PicTools
  • 39
  • 3
-1

The types in the ternary expressions have to be of the same type, so I guess the JLS says that the types are auto-boxed in such a case (it will become Boolean); considering how little checks/optimizations javac does, this is not done here. It's interesting that intellij does complain for example, that a potential NullPointerException will be thrown.

To me, this somehow falls in the same category of:

String s = null;

if (true == true) {

}

if(s == null) {

}

and the like... they all are known at compile time for us, but not for the compiler.

A little bit un-related, but a ternary operator is far from an if statement, Holger once showed me this awesome example with promotion:

boolean b = true;
Object result = b ? Integer.valueOf(42) : Long.valueOf(12);
System.out.println(result.getClass() + "  " + result); // class java.lang.Long  42
Eugene
  • 117,005
  • 15
  • 201
  • 306