Następujący kod generuje NullPointerException:
int num = Integer.getInteger("123");
Czy mój kompilator wywołuje getIntegerwartość 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 getIntegerwartość 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
nulltym przypadku powracaIntegerdo intpowoduje automatyczne rozpakowywanie
Integerjest null, NullPointerExceptionjest rzucanyDo analizowania (String) "123"aby (int) 123można użyć np int Integer.parseInt(String).
Integer Dokumentacja APIInteger.getIntegerOto, 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 lubnulllub jeśli właściwość nie ma poprawnego formatu liczbowego,nullzwracana jest wartość.
Innymi słowy, ta metoda nie ma nic wspólnego z analizowaniem a Stringdo int/Integerwartości, a raczej z System.getPropertymetodą.
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 NullPointerExceptionrzucania. 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.decodezamiast Integer.parseInt, który szuka wiodącego 0xlub 0analizuje 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 Stringparametr 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").