Почему int num = Integer.getInteger («123») вызывает исключение NullPointerException?


106

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

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

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

Что творится?


3
используйте взамен Integer.getValue (). Этот пост в блоге является хорошим объяснением почему: konigsberg.blogspot.in/2008/04/…
Pranaysharma

Ответы:


212

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

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

  • Integer getInteger(String) не делает то, что вы думаете
    • Он возвращается nullв этом случае
  • присвоение от Integerдо intвызывает автоматическую распаковку
    • Так как IntegerIS 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) , презентации Джоша Блоха и Нила Гафтера на технической сессии JavaOne 2009 года. Вот заключительный слайд:

Мораль

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

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

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


На автоответчике

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

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

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

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

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

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


11
Так Integer.getInteger(s)примерно эквивалентно Integer.parseInt(System.getProperty(s))? Я думаю, что предпочитаю второй, хотя он более подробный, потому что он подчеркивает тот факт, что вы извлекаете информацию из свойств системы.
MatrixFrog

5
Как только я опубликовал этот комментарий, я понял, что могу просто посмотреть на фактический источник класса Integer! Я был на правильном пути, за исключением того, что он использует Integer.decodeвместо Integer.parseInt, который ищет начало 0xили 0анализирует число как шестнадцатеричное или восьмеричное, соответственно.
MatrixFrog

Для тех, кто спрашивает почему NullPointerException? : programmers.stackexchange.com/questions/158908/…
ROMANIA_engineer

2
@Oracle, можете ли вы отказаться от java.lang.Integer.getInteger (String), пожалуйста?
mjaggard


6

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.