Il codice seguente genera NullPointerException
:
int num = Integer.getInteger("123");
Il mio compilatore invoca getInteger
su null poiché è statico? Non ha alcun senso!
Cosa sta succedendo?
Il codice seguente genera NullPointerException
:
int num = Integer.getInteger("123");
Il mio compilatore invoca getInteger
su null poiché è statico? Non ha alcun senso!
Cosa sta succedendo?
Risposte:
Ci sono due problemi in gioco qui:
Integer getInteger(String)
non fa quello che pensi che faccia
null
questo caso ritornaInteger
a int
provoca l'unboxing automatico
Integer
è null
, NullPointerException
viene lanciatoPer analizzare (String) "123"
a (int) 123
, è possibile usare, ad esempio int Integer.parseInt(String)
.
Integer
Riferimenti APIInteger.getInteger
Ecco cosa ha da dire la documentazione su ciò che fa questo metodo:
public static Integer getInteger(String nm)
: Determina il valore intero della proprietà di sistema con il nome specificato. Se non è presente una proprietà con il nome specificato, se il nome specificato è vuoto onull
oppure se la proprietà non ha il formato numerico corretto,null
viene restituito.
In altre parole, questo metodo non ha nulla a che fare con l'analisi String
di un int/Integer
valore, ma piuttosto ha a che fare con il System.getProperty
metodo.
Certo, questa può essere una vera sorpresa. È un peccato che la libreria abbia sorprese come questa, ma ti insegna una lezione preziosa: cerca sempre la documentazione per confermare cosa fa un metodo.
Per coincidenza, una variazione di questo problema è stata descritta in Return of the Puzzlers: Schlock and Awe (TS-5186) , Josh Bloch e Neal Gafter's 2009 JavaOne Technical Session Presentation. Ecco la diapositiva conclusiva:
La morale
- Metodi strani e terribili si nascondono nelle biblioteche
- Alcuni hanno nomi dal suono innocuo
- Se il tuo codice si comporta male
- Assicurati di chiamare i metodi giusti
- Leggi la documentazione della libreria
- Per i progettisti API
- Non violare il principio del minimo stupore
- Non violare la gerarchia di astrazione
- Non utilizzare nomi simili per comportamenti estremamente diversi
Per completezza, ci sono anche questi metodi che sono analoghi a Integer.getInteger
:
L'altro problema, ovviamente, è come NullPointerException
viene lanciato. Per concentrarci su questo problema, possiamo semplificare lo snippet come segue:
Integer someInteger = null;
int num = someInteger; // throws NullPointerException!!!
Ecco una citazione da Effective Java 2nd Edition, Item 49: Preferisci i tipi primitivi alle primitive in scatola:
In sintesi, usa le primitive al posto delle primitive inscatolate ogni volta che hai la possibilità di scegliere. I tipi primitivi sono più semplici e veloci. Se devi usare primitive in scatola, fai attenzione! L'autoboxing riduce la verbosità, ma non il pericolo, dell'uso di primitive in scatola. Quando il tuo programma confronta due primitive inscatolate con l'
==
operatore, esegue un confronto di identità, che quasi certamente non è quello che vuoi. Quando il tuo programma esegue calcoli di tipo misto che coinvolgono primitive boxed e unboxed, esegue unboxing e quando il tuo programma esegue unboxing, può lanciareNullPointerException
. Infine, quando il programma inscatola valori primitivi, può risultare in creazioni di oggetti costose e non necessarie.
Ci sono posti in cui non hai altra scelta che usare primitive in box, ad esempio i generici, ma altrimenti dovresti considerare seriamente se la decisione di usare primitive in box è giustificata.
Integer.getInteger(s)
è più o meno equivalente a Integer.parseInt(System.getProperty(s))
? Penso di preferire il secondo, anche se è più dettagliato, perché evidenzia il fatto che stai estraendo informazioni dalle proprietà del sistema.
Integer.decode
invece di Integer.parseInt
, che cerca un interlinea 0x
o 0
per analizzare il numero come esadecimale o ottale, rispettivamente.
NullPointerException
? : programmers.stackexchange.com/questions/158908/…
Da http://konigsberg.blogspot.com/2008/04/integergetinteger-are-you-kidding-me.html :
getInteger "Determina il valore intero della proprietà di sistema con il nome specificato."
Tu vuoi questo:
Integer.parseInt("123")
Si prega di controllare la documentazione del metodo getInteger () . In questo metodo, il String
parametro è una proprietà di sistema che determina il valore intero della proprietà di sistema con il nome specificato. "123" non è il nome di alcuna proprietà di sistema, come discusso qui . Se vuoi convertire questa stringa in int
, usa il metodo come
int num = Integer.parseInt("123")
.