Ich habe diesen Code:
package tests;
import java.util.Hashtable;
public class Tests {
public static void main(String[] args) {
Hashtable<String, Boolean> modifiedItems = new Hashtable<String, Boolean>();
System.out.println("TEST 1");
System.out.println(modifiedItems.get("item1")); // Prints null
System.out.println("TEST 2");
System.out.println(modifiedItems.get("item1") == null); // Prints true
System.out.println("TEST 3");
System.out.println(Boolean.valueOf(null)); // Prints false
System.out.println("TEST 4");
System.out.println(Boolean.valueOf(modifiedItems.get("item1"))); // Produces NullPointerException
System.out.println("FINISHED!"); // Never executed
}
}
Mein Problem ist, dass ich nicht verstehe, warum Test 3 gut funktioniert (es druckt false
und produziert nicht NullPointerException
), während Test 4 a wirft NullPointerException
. Wie Sie in den Tests 1 und 2 sehen können , sind null
und modifiedItems.get("item1")
gleich und null
.
Das Verhalten ist in Java 7 und 8 dasselbe.
java
nullpointerexception
boolean
David E.
quelle
quelle
null
an dieselbe Funktion keine NPE erzeugen! Es gibt einen guten Grund dafür, aber es ist auf den ersten Blick sicherlich verwirrend :-)==
als die Anwendung.Antworten:
Sie müssen genau prüfen, welche Überlastung ausgelöst wird:
Boolean.valueOf(null)
ruft aufBoolean.valueOf(String)
. Das wirft keinenNPE
Even aus, wenn es mit einem Null-Parameter geliefert wird.Boolean.valueOf(modifiedItems.get("item1"))
wird aufgerufenBoolean.valueOf(boolean)
, damodifiedItems
die Werte vom Typ sindBoolean
, was eine Unboxing-Konvertierung erfordert. SeitdemmodifiedItems.get("item1")
istnull
es das Unboxing dieses Wertes - nicht dasBoolean.valueOf(...)
-, das die NPE auslöst.Die Regeln zum Bestimmen, welche Überladung aufgerufen wird, sind ziemlich haarig , aber sie sehen ungefähr so aus:
In einem ersten Durchgang wird nach einer Methodenübereinstimmung gesucht, ohne dass Boxing / Unboxing (oder Methoden mit variabler Arität) zulässig sind.
null
ein akzeptabler Wert für aString
aber nicht istboolean
,Boolean.valueOf(null)
wirdBoolean.valueOf(String)
in diesem Durchgang abgeglichen ;Boolean
ist nicht akzeptabel , entwederBoolean.valueOf(String)
oderBoolean.valueOf(boolean)
, so wird kein Verfahren für die in diesem Durchlauf abgestimmtBoolean.valueOf(modifiedItems.get("item1"))
.In einem zweiten Durchgang wird nach einer Methodenübereinstimmung gesucht, die das Boxen / Entpacken ermöglicht (jedoch immer noch keine Methoden mit variabler Arität).
Boolean
kann entpackt werden,boolean
wird also in diesem DurchgangBoolean.valueOf(boolean)
abgeglichenBoolean.valueOf(modifiedItems.get("item1"))
. Der Compiler muss jedoch eine Unboxing-Konvertierung einfügen, um sie aufzurufen:Boolean.valueOf(modifiedItems.get("item1").booleanValue())
(Es gibt einen dritten Durchgang, der Methoden mit variabler Arität zulässt, aber das ist hier nicht relevant, da die ersten beiden Durchgänge diesen Fällen entsprachen.)
quelle
Boolean.valueOf(modifiedItems.get("item1").booleanValue())
im Quellcode anstelle von verwendenBoolean.valueOf(modifiedItems.get("item1"))
?.booleanValue()
im Ausdruck begraben. Zwei Beobachtungen: 1) Auto (Un) Boxing ist eine bewusste Funktion von Java, um syntaktische Cruft zu entfernen. es selbst zu tun ist möglich, aber nicht idiomatisch; 2) Dies hilft Ihnen überhaupt nicht - es verhindert sicherlich nicht das Auftreten des Problems und gibt auch keine zusätzlichen Informationen, wenn der Fehler auftritt (die Stapelverfolgung wäre identisch, da der ausgeführte Code identisch ist).Da
modifiedItems.get
a zurückgegeben wirdBoolean
(was nicht in a umgewandelt werden kannString
), wird die Signatur verwendetBoolean.valueOf(boolean)
, bei derBoolean
das an ein Grundelement gesendet wirdboolean
. Sobaldnull
es dort zurückgegeben wird, schlägt der Postausgang mit a fehlNullPointerException
.quelle
Methodensignatur
Die Methode
Boolean.valueOf(...)
hat zwei Signaturen:public static Boolean valueOf(boolean b)
public static Boolean valueOf(String s)
Ihr
modifiedItems
Wert istBoolean
. Sie können nicht werfenBoolean
zuString
daher wird die erste Signatur ausgewähltBoolesches Unboxing
In deiner Aussage
was gelesen werden kann als
Gibt jedoch
modifiedItems.get("item1")
zurück,null
so dass Sie im Grunde habenwas offensichtlich zu einem führt
NullPointerException
quelle
Wie Andy schon sehr gut beschrieben hat der Grund von
NullPointerException
:was auf boolesches Unboxing zurückzuführen ist:
konvertiert werden in:
zur Laufzeit und dann wird geworfen,
NullPointerException
wennmodifiedItems.get("item1")
null ist.Jetzt möchte ich noch einen Punkt hinzufügen, dass das Aufheben des Boxens der folgenden Klassen zu ihren jeweiligen Grundelementen auch eine
NullPointerException
Ausnahme erzeugen kann, wenn ihre entsprechenden zurückgegebenen Objekte null sind.Hier ist der Code:
quelle
Eine Möglichkeit, dies zu verstehen, besteht
Boolean.valueOf(null)
darin, dass Java beim Aufrufen genau angewiesen wird, null auszuwerten.Beim
Boolean.valueOf(modifiedItems.get("item1"))
Aufrufen wird Java jedoch angewiesen, einen Wert aus der HashTable des Objekttyps Boolean abzurufen, findet jedoch nicht den Typ Boolean, sondern eine Sackgasse (null), obwohl Boolean erwartet wird. Die NullPointerException-Ausnahme wird ausgelöst, weil die Ersteller dieses Teils von Java entschieden haben, dass diese Situation eine Instanz eines Fehlers im Programm ist, der die Aufmerksamkeit des Programmierers erfordert. (Etwas Unbeabsichtigtes ist passiert.)In diesem Fall ist es eher der Unterschied zwischen der absichtlichen Erklärung, dass Sie beabsichtigt haben, dass die Null vorhanden sein soll, und der Suche nach einem fehlenden Verweis auf ein Objekt (null), bei dem ein Objekt gefunden werden soll.
Weitere Informationen zu NullPointerException finden Sie in dieser Antwort: https://stackoverflow.com/a/25721181/4425643
quelle