Получить доступ

Почему int v = flag ? map.get(key) : 0 (map.get может вернуть null) способно бросить NPE?

MiddleОсновы языка
Коротко

Если одна ветвь тернарного оператора int, а другая Integer, тип всего выражения — int: обёрточная ветвь распаковывается, и null даёт NPE, хотя код выглядит безопасным.

  • Исправление: привести обе ветви к Integer — flag ? map.get(key) : Integer.valueOf(0)
  • Или map.getOrDefault(key, 0)
  • Правило числового продвижения из спецификации языка

А ещё Та же ловушка с Long и long, Boolean и boolean

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Попробуйте сами

Песочница: == против equals и кэш Integer

Подробно

Когда одна ветвь тернарного оператора примитив (int), а другая обёртка (Integer), к выражению применяется числовое расширение и его тип становится int — значит, обёрточная ветвь будет распакована через intValue(). Если выбрана именно она и значение null, получаем NPE, хотя код выглядит безопасным. Лечится тем, что не смешивают обёртку и примитив в одном тернарнике: сначала достают значение с дефолтом (getOrDefault(key, 0)), а уже потом используют.

Что хотят услышать

  • Тип выражения и распаковка.
  • Как исправить.

Частые ошибки

  • Думать, что тернарник вычисляет обе ветви (он вычисляет только выбранную).
  • Смешивать Integer и int в ветвях одного тернарного выражения.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✓Смешение Integer и int делает тип всего тернарника int (числовое расширение), поэтому ветка-обёртка распаковывается — null в ней даёт NPE
  • ✗Тернарный оператор вычисляет обе ветви, поэтому map.get(key) выполняется всегда
  • ✗map.get(key) при отсутствии ключа сам бросает NPE
  • ✗0 неявно приводится к Integer, и сравнение с null падает

Что спросят дальше

  • Как переписать выражение, чтобы NPE стал невозможен?
  • Почему Object o = cond ? 1 : 2.0 даёт 1.0, а не 1?

Разбор темы

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем