Perché int num = Integer.getInteger ("123") genera NullPointerException?


Risposte:


212

La grande immagine

Ci sono due problemi in gioco qui:

  • Integer getInteger(String) non fa quello che pensi che faccia
    • In nullquesto caso ritorna
  • l'assegnazione da Integera intprovoca l'unboxing automatico
    • Dato che Integerè null, NullPointerExceptionviene lanciato

Per analizzare (String) "123"a (int) 123, è possibile usare, ad esempio int Integer.parseInt(String).

Riferimenti

Integer Riferimenti API


Sopra Integer.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 o nulloppure se la proprietà non ha il formato numerico corretto, nullviene restituito.

In altre parole, questo metodo non ha nulla a che fare con l'analisi Stringdi un int/Integervalore, ma piuttosto ha a che fare con il System.getPropertymetodo.

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:

Domande correlate


Sull'autounboxing

L'altro problema, ovviamente, è come NullPointerExceptionviene 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ò lanciare NullPointerException. 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.

Domande correlate


11
Quindi 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.
MatrixFrog

5
Non appena ho pubblicato quel commento, mi sono reso conto che potevo semplicemente guardare la fonte effettiva della classe Integer! Ero sulla strada giusta, tranne per il fatto che usa Integer.decodeinvece di Integer.parseInt, che cerca un interlinea 0xo 0per analizzare il numero come esadecimale o ottale, rispettivamente.
MatrixFrog

Per coloro che chiedono perché NullPointerException? : programmers.stackexchange.com/questions/158908/…
ROMANIA_engineer

2
@Oracle puoi deprecare java.lang.Integer.getInteger (String) per favore?
mjaggard


6

Si prega di controllare la documentazione del metodo getInteger () . In questo metodo, il Stringparametro è 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").

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.