Почему int num = Integer.getInteger ("123") генерирует исключение NullPointerException? - PullRequest
97 голосов
/ 26 июня 2010

Следующий код выдает NullPointerException:

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

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

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

Ответы [ 3 ]

203 голосов
/ 26 июня 2010

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

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

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

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

Ссылки

Integer Ссылки API


Вкл. Integer.getInteger

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

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

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

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

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

Мораль

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

Для полноты изложения существуют также методы, аналогичные Integer.getInteger:

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


При автоматическом подключении

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

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

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

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

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

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

16 голосов
/ 26 июня 2010

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

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

Требуется следующее:

Integer.parseInt("123")
6 голосов
/ 26 июня 2010

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

...