Почему компилятор 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 не может скомпилировать оба случая с одинаковой ошибкой?
Ответы
Ответ 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();