Почему int num = Integer.getInteger("123") генерирует исключение NullPointerException?

Следующий код бросает NullPointerException:

int num = Integer.getInteger("123");

Мой компилятор вызывает getInteger на нуле, так как это статично? Это не имеет никакого смысла!

Что происходит?

3 ответа

Решение

Большая картина

Здесь есть две проблемы:

  • Integer getInteger(String) не делает то, что вы думаете, что делает
    • Возвращается null в этом случае
  • назначение от Integer в int вызывает автоматическую распаковку
    • Так как Integer является null, NullPointerException брошен

Разобрать (String) "123" в (int) 123 Вы можете использовать, например, int Integer.parseInt(String),

Рекомендации

Integer Ссылки на API

  • static int parseInt(String)
  • static Integer getInteger(String)

На Integer.getInteger

Вот что говорит документация о том, что делает этот метод:

public static Integer getInteger(String nm): Определяет целочисленное значение системного свойства с указанным именем. Если нет свойства с указанным именем, если указанное имя пустое или null или если свойство не имеет правильный числовой формат, то null возвращается

Другими словами, этот метод не имеет ничего общего с разбором String для int/Integer ценность, а точнее, это связано с System.getProperty метод.

По общему признанию это может быть довольно неожиданным. К сожалению, у библиотеки есть такие сюрпризы, как это, но она преподает вам ценный урок: всегда ищите документацию, чтобы подтвердить, что метод делает.

По совпадению, вариант этой проблемы был показан в " Возвращении головоломок: Шлок и Трепет" (TS-5186), Джош Блох и Нил Гафтер в 2009 году на технической сессии JavaOne. Вот заключительный слайд:

Мораль

  • Странные и страшные методы скрываются в библиотеках
    • У некоторых есть безобидные звучащие имена
  • Если ваш код плохо себя ведет
    • Убедитесь, что вы вызываете правильные методы
    • Прочитайте документацию библиотеки
  • Для дизайнеров API
    • Не нарушайте принцип наименьшего удивления
    • Не нарушайте иерархию абстракций
    • Не используйте похожие имена для совершенно разных поведений

Для полноты, есть также эти методы, которые аналогичны Integer.getInteger:

  • Boolean.getBoolean(String)
  • Long.getLong(String)

Смежные вопросы


На автобокс

Другая проблема, конечно, в том, как NullPointerException брошен Чтобы сосредоточиться на этой проблеме, мы можем упростить фрагмент кода следующим образом:

Integer someInteger = null;
int num = someInteger; // throws NullPointerException!!!

Вот цитата из Effective Java 2nd Edition, Item 49: Предпочитайте примитивные типы коробочным примитивам:

Таким образом, используйте примитивы в предпочтении по сравнению с примитивом в штучной упаковке, когда у вас есть выбор Примитивные типы проще и быстрее. Если вы должны использовать коробочные примитивы, будьте осторожны! Автобокс уменьшает многословность, но не опасность использования коробочных примитивов. Когда ваша программа сравнивает два коробочных примитива с == оператор, он делает сравнение идентичности, что почти наверняка не то, что вы хотите. Когда ваша программа выполняет вычисления смешанного типа с использованием коробочных и распакованных примитивов, она выполняет распаковку, а когда ваша программа выполняет распаковку, она может выдать NullPointerException, Наконец, когда ваша программа упаковывает примитивные значения, это может привести к дорогостоящим и ненужным созданиям объектов.

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

Смежные вопросы

С http://konigsberg.blogspot.com/2008/04/integergetinteger-are-you-kidding-me.html:

getInteger 'Определяет целочисленное значение системного свойства с указанным именем.'

Вы хотите это:

Integer.parseInt("123")

Пожалуйста, ознакомьтесь с документацией метода getInteger (). В этом методе String Параметр - это системное свойство, которое определяет целочисленное значение системного свойства с указанным именем. "123" не является именем какого-либо системного свойства, как обсуждено здесь. Если вы хотите преобразовать эту строку в intзатем используйте метод как int num = Integer.parseInt("123"),

Другие вопросы по тегам