Почему int v = flag ? map.get(key) : 0 (map.get может вернуть null) способно бросить NPE?
Если одна ветвь тернарного оператора int, а другая Integer, тип всего выражения — int: обёрточная ветвь распаковывается, и null даёт NPE, хотя код выглядит безопасным.
- Исправление: привести обе ветви к Integer — flag ? map.get(key) : Integer.valueOf(0)
- Или map.getOrDefault(key, 0)
- Правило числового продвижения из спецификации языка
А ещё Та же ловушка с Long и long, Boolean и boolean
Подробно
Когда одна ветвь тернарного оператора примитив (int), а другая обёртка (Integer), к выражению применяется числовое расширение и его тип становится int — значит, обёрточная ветвь будет распакована через intValue(). Если выбрана именно она и значение null, получаем NPE, хотя код выглядит безопасным. Лечится тем, что не смешивают обёртку и примитив в одном тернарнике: сначала достают значение с дефолтом (getOrDefault(key, 0)), а уже потом используют.
Что хотят услышать
- Тип выражения и распаковка.
- Как исправить.
Частые ошибки
- Думать, что тернарник вычисляет обе ветви (он вычисляет только выбранную).
- Смешивать Integer и int в ветвях одного тернарного выражения.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✓Тип тернарника становится int, и ветка Integer распаковывается — null даёт NPE
- ✗Тернарный оператор вычисляет обе ветви, поэтому map.get(key) падает всегда
- ✗map.get(key) при отсутствии ключа сам бросает NPE
- ✗0 неявно приводится к Integer, и сравнение с null падает
Что спросят дальше
- Как переписать выражение, чтобы NPE стал невозможен?
- Почему Object o = cond ? 1 : 2.0 даёт 1.0, а не 1?
Разбор темы
- Примитивы, обёртки и Integer cache
Восемь примитивов и их диапазоны, autoboxing, кэш Integer и ловушка ==, NPE при распаковке и цена боксинга.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.