Почему 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)
Смежные вопросы
- Самое удивительное нарушение принципа наименьшего удивления
- Самый неудобный / вводящий в заблуждение метод в Java Base API?
На автобокс
Другая проблема, конечно, в том, как NullPointerException
брошен Чтобы сосредоточиться на этой проблеме, мы можем упростить фрагмент кода следующим образом:
Integer someInteger = null;
int num = someInteger; // throws NullPointerException!!!
Вот цитата из Effective Java 2nd Edition, Item 49: Предпочитайте примитивные типы коробочным примитивам:
Таким образом, используйте примитивы в предпочтении по сравнению с примитивом в штучной упаковке, когда у вас есть выбор Примитивные типы проще и быстрее. Если вы должны использовать коробочные примитивы, будьте осторожны! Автобокс уменьшает многословность, но не опасность использования коробочных примитивов. Когда ваша программа сравнивает два коробочных примитива с
==
оператор, он делает сравнение идентичности, что почти наверняка не то, что вы хотите. Когда ваша программа выполняет вычисления смешанного типа с использованием коробочных и распакованных примитивов, она выполняет распаковку, а когда ваша программа выполняет распаковку, она может выдатьNullPointerException
, Наконец, когда ваша программа упаковывает примитивные значения, это может привести к дорогостоящим и ненужным созданиям объектов.
Есть места, где у вас нет выбора, кроме как использовать примитивы в штучной упаковке, например, дженерики, но в противном случае вам следует серьезно подумать, оправдано ли решение использовать примитивы в штучной упаковке.
Смежные вопросы
- В чем разница между int и Integer в Java/C#?
- Почему автобокс в Java позволяет мне иметь 3 возможных значения для логического значения?
- Гарантируется ли, что новое целое число (i) == i в Java? (ДА!!!)
- При сравнении двух целых чисел в Java происходит автоматическая распаковка? (НЕТ!!!)
- Java noob: обобщение только для объектов? (Да, к сожалению)
С 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")
,