Почему компилятор Java иногда допускает unboxing null? - программирование

Почему компилятор Java иногда допускает unboxing null?

Например:

int anInt = null;

не работает во время компиляции, но

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;
}

не работает (обычно) во время выполнения. Попытка вернуть только null также приведет к ошибке компиляции, поэтому я предполагаю, что есть что-то о том, что есть несколько путей, которые заставляют компилятор заключить, что null потенциально является autoboxed int? Почему javac не может скомпилировать оба случая с одинаковой ошибкой?

4b9b3361

Ответ 1

В первом случае компилятор знает, что вы пытаетесь распаковать константу времени компиляции null.

Во втором случае тип условного выражения Integer, поэтому вы эффективно пишете:

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

... поэтому unboxing не происходит в постоянном выражении, и компилятор разрешит его.

Если вы изменили его, чтобы заставить условное выражение быть типом int путем распаковки там, оно потерпит неудачу:

// Compile-time failure
return new Random().nextBoolean() ? 1 : (int) null;

Ответ 2

Бокс частично скрывает различие между примитивами и соответствующими объектами-обертками, но он не удаляет его.

Есть два различия, которые не изменяются в боксе:

  • объекты могут быть пустыми, а примитивы не могут
  • объекты имеют как состояние, так и идентичность, тогда как примитивы имеют только состояние (значение)

Иногда эти различия могут вызвать проблемы при использовании бокса.

Некоторые моменты для запоминания:

  • Будьте осторожны с нулями. Автоматическая распаковка нулевого объекта приведет к NullPointerException.
  • сравнение элементов с == и equals должно выполняться с осторожностью.

Ответ 3

Вы не можете назначить null для int

    int anInt = null;

Java разрешает это, так как вы не назначаете null для int

    System.out.println("" + getSomeVal()); //null was just converted to a srting and was printed

Если вы выполните это, вы можете получить ошибку

    int anInt = getSomeVal();