Чому int num = Integer.getInteger ("123") кидає NullPointerException?


106

Наступний код кидає NullPointerException:

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

Чи може мій компілятор викликати getIntegernull, оскільки він статичний? Це не має сенсу!

Що відбувається?


3
використовуйте замість Integer.getValue (). Ця публікація в блозі - це гарне пояснення, чому: konigsberg.blogspot.in/2008/04/…
Пранаярма

Відповіді:


212

Велика картина

Тут зіграно два питання:

  • 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:

Пов'язані питання


На автобоксингу

Інше питання, звичайно, - як NullPointerExceptionкидається. Щоб зосередитись на цьому питанні, ми можемо спростити фрагмент наступним чином:

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

Ось цитата з Ефективного Java 2-го видання, пункт 49: Віддавайте перевагу примітивним типам, а не примітивним коробкам:

Підсумовуючи це, використовуйте примітиви, надаючи перевагу боксу примітивним, коли у вас є вибір. Примітивні типи простіші та швидші. Якщо вам потрібно скористатися коробками примітивів, будьте обережні! Автобоксинг зменшує багатослівність, але не небезпеку використання приміщень, що містять коробки. Коли ваша програма порівнює два примітивні коробки з ==оператором, вона проводить порівняння ідентичності, що майже точно не те, що ви хочете. Коли у вашій програмі проводяться обчислення змішаного типу із залученням коробкових та небіткових примітивів, вона виконує розпакування, а коли ваша програма розпаковує, вона може кидати NullPointerException. Нарешті, коли у вашій програмі зберігаються примітивні значення, це може спричинити за собою дорогі та непотрібні створення об’єктів.

Є місця, де у вас немає іншого вибору, крім використання приміщень, що містять коробки, наприклад, дженерики, але в іншому випадку слід серйозно задуматися, чи є рішення про використання боксированних примітивів виправданим.

Пов'язані питання


11
Так Integer.getInteger(s)це приблизно еквівалентно Integer.parseInt(System.getProperty(s))? Я думаю, що я віддаю перевагу другому, хоча він є більш багатослівним, оскільки він підкреслює той факт, що ви витягуєте інформацію з властивостей системи.
MatrixFrog

5
Як тільки я опублікував цей коментар, я зрозумів, що можу просто подивитися на власне джерело класу Integer! Я був на правильному шляху, за винятком того, що він використовує Integer.decodeзамість того Integer.parseInt, що шукає ведучий 0xабо 0для розбору числа відповідно шістнадцятковий або восьмеричний.
MatrixFrog

Для тих, хто запитує, чому NullPointerException? : programmers.stackexchange.com/questions/158908/…
ROMANIA_engineer

2
@Oracle чи можете ви скасувати java.lang.Integer.getInteger (String)?
mjaggard


6

Перевірте документацію методу getInteger () . У цьому способі Stringпараметр - це властивість системи, яка визначає ціле значення властивості системи із заданим іменем. "123" - це не ім'я жодної системної властивості, про яку йдеться тут . Якщо ви хочете перетворити цей рядок у int, використовуйте метод як int num = Integer.parseInt("123").

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.