Следующий код выдает NullPointerException
:
int num = Integer.getInteger("123");
Вызывает ли мой компилятор значение getInteger
null, поскольку оно статично? В этом нет никакого смысла!
Что творится?
Следующий код выдает NullPointerException
:
int num = Integer.getInteger("123");
Вызывает ли мой компилятор значение getInteger
null, поскольку оно статично? В этом нет никакого смысла!
Что творится?
Ответы:
Здесь есть две проблемы:
Integer getInteger(String)
не делает то, что вы думаете
null
в этом случаеInteger
до int
вызывает автоматическую распаковку
Integer
IS null
, NullPointerException
брошеноДля того, чтобы разобрать , (String) "123"
чтобы (int) 123
, вы можете использовать , например int Integer.parseInt(String)
.
Integer
Ссылки APIInteger.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
. Наконец, когда ваша программа упаковывает примитивные значения, это может привести к созданию дорогостоящих и ненужных объектов.
Есть места, где у вас нет выбора, кроме как использовать упакованные примитивы, например дженерики, но в противном случае вам следует серьезно подумать, оправдано ли решение использовать упакованные примитивы.
Integer.getInteger(s)
примерно эквивалентно Integer.parseInt(System.getProperty(s))
? Я думаю, что предпочитаю второй, хотя он более подробный, потому что он подчеркивает тот факт, что вы извлекаете информацию из свойств системы.
Integer.decode
вместо Integer.parseInt
, который ищет начало 0x
или 0
анализирует число как шестнадцатеричное или восьмеричное, соответственно.
NullPointerException
? : programmers.stackexchange.com/questions/158908/…
С 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")
.