Następujący kod generuje NullPointerException
:
int num = Integer.getInteger("123");
Czy mój kompilator wywołuje getInteger
wartość null, ponieważ jest statyczny? To nie ma sensu!
Co się dzieje?
Następujący kod generuje NullPointerException
:
int num = Integer.getInteger("123");
Czy mój kompilator wywołuje getInteger
wartość null, ponieważ jest statyczny? To nie ma sensu!
Co się dzieje?
Odpowiedzi:
Mamy tu do czynienia z dwoma problemami:
Integer getInteger(String)
nie robi tego, co myślisz, że robi
null
tym przypadku powracaInteger
do int
powoduje automatyczne rozpakowywanie
Integer
jest null
, NullPointerException
jest rzucanyDo analizowania (String) "123"
aby (int) 123
można użyć np int Integer.parseInt(String)
.
Integer
Dokumentacja APIInteger.getInteger
Oto, co dokumentacja ma do powiedzenia na temat tego, co robi ta metoda:
public static Integer getInteger(String nm)
: Określa wartość całkowitą właściwości systemowej o określonej nazwie. Jeśli nie ma właściwości o określonej nazwie, jeśli określona nazwa jest pusta lubnull
lub jeśli właściwość nie ma poprawnego formatu liczbowego,null
zwracana jest wartość.
Innymi słowy, ta metoda nie ma nic wspólnego z analizowaniem a String
do int/Integer
wartości, a raczej z System.getProperty
metodą.
Trzeba przyznać, że może to być sporym zaskoczeniem. Szkoda, że biblioteka ma takie niespodzianki, ale daje cenną lekcję: zawsze sprawdzaj dokumentację, aby potwierdzić, co robi metoda.
Zbiegiem okoliczności odmiana tego problemu została przedstawiona w prezentacji „ Return of the Puzzlers: Schlock and Awe (TS-5186)” , Josha Blocha i Neala Gaftera w 2009 roku w prezentacji JavaOne Technical Session. Oto slajd podsumowujący:
Morał
- W bibliotekach czają się dziwne i straszne metody
- Niektóre mają niewinnie brzmiące nazwiska
- Jeśli twój kod źle się zachowuje
- Upewnij się, że wywołujesz właściwe metody
- Przeczytaj dokumentację biblioteki
- Dla projektantów API
- Nie naruszaj zasady najmniejszego zdziwienia
- Nie naruszaj hierarchii abstrakcji
- Nie używaj podobnych nazw dla bardzo różnych zachowań
Dla kompletności istnieją również te metody, które są analogiczne do Integer.getInteger
:
Inną kwestią jest oczywiście sposób NullPointerException
rzucania. Aby skupić się na tym problemie, możemy uprościć fragment w następujący sposób:
Integer someInteger = null;
int num = someInteger; // throws NullPointerException!!!
Oto cytat z Effective Java 2nd Edition, pozycja 49: Preferuj typy pierwotne od prymitywów pudełkowych:
Podsumowując, zawsze używaj prymitywów zamiast prymitywów pudełkowych, kiedy tylko masz wybór. Typy prymitywne są prostsze i szybsze. Jeśli musisz używać prymitywów w pudełkach, bądź ostrożny! Autoboxing zmniejsza szczegółowość, ale nie ogranicza niebezpieczeństwa używania pudełkowych prymitywów. Kiedy twój program porównuje dwa prymitywy w pudełku z
==
operatorem, dokonuje porównania tożsamości, co prawie na pewno nie jest tym, czego chcesz. Kiedy twój program wykonuje obliczenia typu mieszanego z udziałem prymitywów zapakowanych i nieopakowanych, robi to rozpakowywanie, a kiedy twój program rozpakowuje, może rzucaćNullPointerException
. Wreszcie, gdy program zawiera prymitywne wartości, może to spowodować kosztowne i niepotrzebne tworzenie obiektów.
Są miejsca, w których nie masz innego wyboru, jak tylko użyć prymitywów pudełkowych, np. Generycznych, ale w przeciwnym razie powinieneś poważnie rozważyć, czy decyzja o użyciu prymitywów pudełkowych jest uzasadniona.
Integer.getInteger(s)
jest z grubsza równoważne Integer.parseInt(System.getProperty(s))
? Myślę, że wolę drugą, chociaż jest bardziej rozwlekła, ponieważ podkreśla fakt, że pobierasz informacje z właściwości systemu.
Integer.decode
zamiast Integer.parseInt
, który szuka wiodącego 0x
lub 0
analizuje liczbę odpowiednio jako szesnastkową lub ósemkową.
NullPointerException
? : programmers.stackexchange.com/questions/158908/ ...
Z http://konigsberg.blogspot.com/2008/04/integergetinteger-are-you-kidding-me.html :
getInteger 'Określa wartość całkowitą właściwości systemowej o określonej nazwie.'
Chcesz to:
Integer.parseInt("123")
Sprawdź dokumentację metody getInteger () . W tej metodzie String
parametr jest właściwością systemową, która określa wartość całkowitą właściwości systemowej o określonej nazwie. Jak omówiono tutaj, „123” nie jest nazwą żadnej właściwości systemowej . Jeśli chcesz przekonwertować ten ciąg na int
, użyj metody jako
int num = Integer.parseInt("123")
.