Почему int num = Integer.getInteger("123") выдает исключение NullPointerException?
-
30-09-2019 - |
Вопрос
Следующий код выдает NullPointerException
:
int num = Integer.getInteger("123");
Мой компилятор вызывает getInteger
на нуле, поскольку он статический?Это не имеет никакого смысла!
Что происходит?
Решение
Большая картина
Здесь есть две проблемы:
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), Презентация Джоша Блоха и Нила Гафтера на технической сессии JavaOne 2009 года.Вот заключительный слайд:
Мораль
- В библиотеках таятся странные и ужасные методы
- У некоторых безобидные имена.
- Если ваш код работает неправильно
- Убедитесь, что вы вызываете правильные методы
- Прочтите документацию библиотеки
- Для дизайнеров API
- Не нарушайте принцип наименьшего удивления
- Не нарушайте иерархию абстракций
- Не используйте одинаковые имена для совершенно разных моделей поведения.
Для полноты картины существуют также методы, аналогичные Integer.getInteger
:
Связанные вопросы
- Самое поразительное нарушение принципа наименьшего удивления
- Самый неуклюжий/вводящий в заблуждение метод в Java Base API?
Об автораспаковке
Другой вопрос, конечно, в том, как NullPointerException
бросают.Чтобы сосредоточиться на этой проблеме, мы можем упростить фрагмент следующим образом:
Integer someInteger = null;
int num = someInteger; // throws NullPointerException!!!
Вот цитата из «Эффективной Java, 2-е издание», пункт 49:Предпочитайте примитивные типы коробочным примитивам:
Таким образом, используйте примитивы, а не коробочные примитивы, когда у вас есть выбор.Примитивные типы проще и быстрее.Если вам необходимо использовать коробочные примитивы, будьте осторожны!Автоупаковка уменьшает многословие, но не опасность использования упакованных примитивов.Когда ваша программа сравнивает два упакованных примитива с
==
оператор, он выполняет сравнение идентификаторов, что почти наверняка не то, что вам нужно.Когда ваша программа выполняет вычисления смешанного типа, включающие упакованные и неупакованные примитивы, она выполняет распаковку, а когда ваша программа выполняет распаковку, она может выдать ошибкуNullPointerException
.Наконец, когда ваша программа упаковывает примитивные значения, это может привести к дорогостоящему и ненужному созданию объектов.
Есть места, где у вас нет другого выбора, кроме как использовать коробочные примитивы, например.дженерики, но в противном случае вам следует серьезно задуматься, оправдано ли решение использовать коробочные примитивы.
Связанные вопросы
- В чем разница между int и Integer в Java/C#?
- Почему автобокс в Java позволяет мне иметь три возможных значения для логического значения?
- Гарантировано ли, что new Integer(i) == i в Java? (ДА!!!)
- При сравнении двух целых чисел в Java происходит ли автоматическая распаковка? (НЕТ!!!)
- Ява-нуб:дженерики только для объектов? (Да, к сожалению)
Другие советы
От 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")
.