Вопрос:

Почему int num = Integer.getInteger ("123") генерирует исключение NullPointerException?

java integer nullpointerexception api-design autoboxing

56021 просмотра

3 ответа

1387 Репутация автора

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

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

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

Что происходит?

Автор: user282886 Источник Размещён: 26.06.2010 09:18

Ответы (3)


207 плюса

300214 Репутация автора

Решение

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

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

  • 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) , Джош Блох и Нил Гафтер в 2009 году на технической сессии JavaOne. Вот заключительный слайд:

Мораль

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

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

Смежные вопросы


На автобокс

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

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

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

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

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

Смежные вопросы

Автор: polygenelubricants Размещён: 26.06.2010 09:18

16 плюса

33648 Репутация автора

С http://konigsberg.blogspot.com/2008/04/integergetinteger-are-you-kidding-me.html :

getInteger 'Определяет целочисленное значение системного свойства с указанным именем.'

Вы хотите это:

Integer.parseInt("123")
Автор: Kieren Johnstone Размещён: 26.06.2010 09:20

6 плюса

192 Репутация автора

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

Автор: Sonal Patil Размещён: 26.06.2010 09:43
Вопросы из категории :
32x32