Warum löst int num = Integer.getInteger ("123") eine NullPointerException aus?

106

Der folgende Code wirft NullPointerException:

int num = Integer.getInteger("123");

Ruft mein Compiler getIntegernull auf, da er statisch ist? Das macht keinen Sinn!

Was ist los?

user282886
quelle
3
Verwenden Sie stattdessen Integer.getValue (). Dieser Blog-Beitrag ist eine gute Erklärung, warum: konigsberg.blogspot.in/2008/04/…
Pranaysharma

Antworten:

212

Das große Bild

Hier spielen zwei Probleme eine Rolle:

  • Integer getInteger(String) tut nicht das, was du denkst
    • Es gibt nullin diesem Fall
  • Die Zuweisung von Integerbis intbewirkt das automatische Entpacken
    • Da das Integerheißt null, NullPointerExceptiongeworfen wird

Analysieren (String) "123"zu (int) 123können Sie zB verwenden int Integer.parseInt(String).

Verweise

Integer API-Referenzen


Auf Integer.getInteger

In der Dokumentation wird Folgendes zu dieser Methode gesagt:

public static Integer getInteger(String nm): Bestimmt den ganzzahligen Wert der Systemeigenschaft mit dem angegebenen Namen. Wenn es keine Eigenschaft mit dem angegebenen Namen gibt, wenn der angegebene Name leer nullist oder wenn die Eigenschaft nicht das richtige numerische Format hat, nullwird zurückgegeben.

Mit anderen Worten, diese Methode hat nichts mit dem Parsen von a Stringzu einem int/IntegerWert zu tun, sondern mit der System.getPropertyMethode.

Zugegeben, das kann eine ziemliche Überraschung sein. Es ist bedauerlich, dass die Bibliothek solche Überraschungen bietet, aber sie lehrt Sie eine wertvolle Lektion: Schauen Sie immer in der Dokumentation nach, um zu bestätigen, was eine Methode tut.

Zufälligerweise wurde eine Variante dieses Problems in Return of the Puzzlers vorgestellt: Schlock und Awe (TS-5186) , Josh Bloch und Neal Gafters Präsentation der JavaOne Technical Session 2009. Hier ist die abschließende Folie:

Die Moral

  • In Bibliotheken lauern seltsame und schreckliche Methoden
    • Einige haben harmlos klingende Namen
  • Wenn sich Ihr Code schlecht verhält
    • Stellen Sie sicher, dass Sie die richtigen Methoden aufrufen
    • Lesen Sie die Bibliotheksdokumentation
  • Für API-Designer
    • Verstoße nicht gegen das Prinzip des geringsten Erstaunens
    • Verletzen Sie nicht die Abstraktionshierarchie
    • Verwenden Sie keine ähnlichen Namen für völlig unterschiedliche Verhaltensweisen

Der Vollständigkeit halber gibt es auch diese Methoden, die analog sind zu Integer.getInteger:

Verwandte Fragen


Beim Autounboxen

Das andere Problem ist natürlich, wie das NullPointerExceptiongeworfen wird. Um uns auf dieses Problem zu konzentrieren, können wir das Snippet wie folgt vereinfachen:

Integer someInteger = null;
int num = someInteger; // throws NullPointerException!!!

Hier ist ein Zitat aus Effective Java 2nd Edition, Punkt 49: Bevorzugen Sie primitive Typen gegenüber primitiven Boxen:

Zusammenfassend lässt sich sagen, dass Sie Primitive gegenüber Boxed-Primitiven bevorzugen, wenn Sie die Wahl haben. Primitive Typen sind einfacher und schneller. Wenn Sie Grundelemente in Schachteln verwenden müssen, seien Sie vorsichtig! Autoboxing reduziert die Ausführlichkeit, aber nicht die Gefahr der Verwendung von Grundelementen in Schachteln. Wenn Ihr Programm zwei Grundelemente mit dem ==Operator vergleicht, führt es einen Identitätsvergleich durch, der mit ziemlicher Sicherheit nicht Ihren Wünschen entspricht. Wenn Ihr Programm Berechnungen vom gemischten Typ mit primitiven Box- und Unboxed-Grundelementen ausführt, wird das Unboxing ausgeführt, und wenn Ihr Programm das Unboxing ausführt, kann es ausgelöst werden NullPointerException. Wenn Ihr Programm primitive Werte enthält, kann dies zu kostspieligen und unnötigen Objekterstellungen führen.

Es gibt Orte, an denen Sie keine andere Wahl haben, als Box-Primitive zu verwenden, z. B. Generika. Andernfalls sollten Sie ernsthaft überlegen, ob eine Entscheidung zur Verwendung von Box-Primitiven gerechtfertigt ist.

Verwandte Fragen

Polygenschmierstoffe
quelle
11
Ist Integer.getInteger(s)also ungefähr gleichbedeutend mit Integer.parseInt(System.getProperty(s))? Ich glaube, ich bevorzuge die zweite, obwohl sie ausführlicher ist, weil sie die Tatsache hervorhebt, dass Sie Informationen aus den Systemeigenschaften abrufen.
MatrixFrog
5
Sobald ich diesen Kommentar gepostet hatte, wurde mir klar, dass ich mir nur die tatsächliche Quelle der Integer-Klasse ansehen konnte! Ich war auf dem richtigen Weg, außer dass es Integer.decodestattdessen verwendet Integer.parseInt, was nach einem führenden Wert sucht 0xoder 0die Zahl als hexadezimal bzw. oktal analysiert.
MatrixFrog
Für diejenigen, die fragen, warum NullPointerException? : programmers.stackexchange.com/questions/158908/…
ROMANIA_engineer
2
@Oracle Kannst du java.lang.Integer.getInteger (String) bitte ablehnen?
mjaggard
6

Bitte überprüfen Sie die Dokumentation der Methode getInteger () . Bei dieser Methode ist der StringParameter eine Systemeigenschaft, die den ganzzahligen Wert der Systemeigenschaft mit dem angegebenen Namen bestimmt. "123" ist nicht der Name einer Systemeigenschaft, wie hier erläutert . Wenn Sie diesen String in konvertieren möchten int, verwenden Sie die Methode als int num = Integer.parseInt("123").

Sonal Patil
quelle