Наступний код кидає NullPointerException
:
int num = Integer.getInteger("123");
Чи може мій компілятор викликати getInteger
null, оскільки він статичний? Це не має сенсу!
Що відбувається?
Наступний код кидає NullPointerException
:
int num = Integer.getInteger("123");
Чи може мій компілятор викликати getInteger
null, оскільки він статичний? Це не має сенсу!
Що відбувається?
Відповіді:
Тут зіграно два питання:
Integer getInteger(String)
не робить те, що ви думаєте, що це робить
null
цьому випадку він повертаєтьсяInteger
до int
викликає автоматичне розпакування
Integer
є 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!!!
Ось цитата з Ефективного Java 2-го видання, пункт 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")
.