Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the Java compiler sometimes allow the unboxing of null?

For example:

int anInt = null;

fails at compile time but

public static void main(String[] args) {
  for (int i = 0; i < 10; i++) {
    System.out.println("" + getSomeVal());
  }
}
public static int getSomeVal() {
   return new Random().nextBoolean() ? 1 : null;
}

fails (usually) at run time. Trying to return just null will also result in a compile error, so I assume there is something about having multiple paths that causes the compiler to infer that null is potentially an autoboxed int? Why can javac not fail to compile both cases with the same error?

like image 555
MilesHampson Avatar asked Aug 10 '12 08:08

MilesHampson


2 Answers

In the first case, the compiler knows that you're trying to unbox a compile-time constant of null.

In the second case, the type of the conditional expression is Integer, so you're effectively writing:

Integer tmp = new Random().nextBoolean() ? 1 : null;
return (int) tmp;

... so the unboxing isn't happening on a constant expression, and the compiler will allow it.

If you changed it to force the conditional expression to be of type int by unboxing there, it would fail:

// Compile-time failure
return new Random().nextBoolean() ? 1 : (int) null;
like image 135
Jon Skeet Avatar answered Sep 16 '22 12:09

Jon Skeet


Boxing partially hides the distinction between primitives and corresponding wrapper objects, but it doesn't remove it.

There are two distinctions which are not changed by boxing:

  • objects can be null, while primitives cannot
  • objects have both state and identity, while primitives have only state (the value)

Occasionally, these differences can cause problems when using boxing.

Some points to remember :

  • be careful with nulls. Auto-unboxing a null object will cause a NullPointerException.
  • comparing items with == and equals must be done with care.
like image 38
NPKR Avatar answered Sep 19 '22 12:09

NPKR