Следующий код выдает NullPointerException
:
int num = Integer.getInteger("123");
Вызывает ли мой компилятор getInteger
с нулевым значением, поскольку он статичен? В этом нет никакого смысла!
Что происходит?
Следующий код выдает NullPointerException
:
int num = Integer.getInteger("123");
Вызывает ли мой компилятор getInteger
с нулевым значением, поскольку он статичен? В этом нет никакого смысла!
Что происходит?
Здесь есть две проблемы:
Integer getInteger(String)
doesn't do what you think it does
null
in this caseInteger
to int
causes auto-unboxing
Integer
is null
, NullPointerException
is thrownЧтобы разобрать (String) "123"
на (int) 123
, вы можете использовать, например, int Integer.parseInt(String)
.
Integer
Справочные материалы по APIInteger.getInteger
Вот что говорится в документации о том, что делает этот метод:
_15 _: определяет целочисленное значение системного свойства с указанным именем. Если нет свойства с указанным именем, если указанное имя пустое или
null
, или если свойство не имеет правильного числового формата, то возвращаетсяnull
.
Другими словами, этот метод не имеет ничего общего с преобразованием String
в значение int/Integer
, а скорее связан с _ 20_.
По общему признанию, это может быть большим сюрпризом. К сожалению, в библиотеке есть такие сюрпризы, но она преподает вам ценный урок: всегда ищите документацию, чтобы узнать, что делает метод.
По совпадению, вариант этой проблемы был описан в < em> Возвращение головоломок: Шлок и трепет (TS-5186), презентация технической сессии JavaOne 2009 Джоша Блоха и Нила Гафтера. Вот заключительный слайд:
Мораль
- Strange and terrible methods lurk in libraries
- Some have innocuous sounding names
- If your code misbehaves
- Make sure you're calling the right methods
- Прочтите документацию библиотеки
- For API designers
- Don't violate the principle of least astonishment
- Не нарушайте иерархию абстракций
- Не используйте одинаковые имена для сильно различающегося поведения
Для полноты картины существуют также методы, аналогичные Integer.getInteger
:
Другой вопрос, конечно, заключается в том, как бросить NullPointerException
. Чтобы сосредоточиться на этой проблеме, мы можем упростить фрагмент следующим образом:
Integer someInteger = null;
int num = someInteger; // throws NullPointerException!!!
Вот цитата из Effective Java 2nd Edition, пункт 49: Предпочитайте примитивные типы упакованным примитивам:
Таким образом, используйте примитивы вместо примитивов в штучной упаковке, когда у вас есть выбор. Примитивные типы проще и быстрее. Если вы должны использовать примитивы в штучной упаковке, будьте осторожны! Автобокс снижает многословие, но не снижает опасность использования упакованных примитивов. Когда ваша программа сравнивает два упакованных примитива с оператором
==
, она выполняет сравнение идентичности, что почти наверняка не то, что вам нужно. Когда ваша программа выполняет вычисления смешанного типа с использованием упакованных и распакованных примитивов, она выполняет распаковку, а когда ваша программа выполняет распаковку, она может выброситьNullPointerException
. Наконец, когда ваша программа упаковывает примитивные значения, это может привести к созданию дорогостоящих и ненужных объектов.
Есть места, где у вас нет выбора, кроме как использовать коробочные примитивы, например дженерики, но в противном случае вам следует серьезно подумать, оправдано ли решение использовать упакованные примитивы.
Integer.getInteger(s)
примерно эквивалентно Integer.parseInt(System.getProperty(s))
? Я думаю, что предпочитаю второй, хотя он более подробный, потому что он подчеркивает тот факт, что вы извлекаете информацию из свойств системы.
- person MatrixFrog; 26.06.2010
Integer.decode
вместо Integer.parseInt
, который ищет начальные 0x
или 0
для анализа числа как шестнадцатеричного или восьмеричного соответственно.
- person MatrixFrog; 26.06.2010
NullPointerException
?: programmers.stackexchange.com/questions/158908/
- person Elrond_EGLDer; 28.12.2015
Из 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")
.