Nead Klarstellung für folgenden Code:
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample.append("B");
System.out.println(sample);
Dies wird gedruckt, B
so dass Beweise sample
und referToSample
Objekte auf dieselbe Speicherreferenz verweisen.
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
sample.append("A");
referToSample.append("B");
System.out.println(referToSample);
Dies wird gedruckt AB
, was auch das gleiche beweist.
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample = null;
referToSample.append("A");
System.out.println(sample);
Offensichtlich wird dies werfen, NullPointerException
weil ich versuche, append
eine Nullreferenz aufzurufen .
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample = null;
sample.append("A");
System.out.println(sample);
Hier ist meine Frage, warum das letzte Codebeispiel nicht ausgelöst wird, NullPointerException
denn was ich aus den ersten beiden Beispielen sehe und verstehe, ist, wenn zwei Objekte auf dasselbe Objekt verweisen und wenn wir einen Wert ändern, wird es auch auf andere reflektiert, weil beide auf zeigen gleiche Speicherreferenz. Warum gilt diese Regel hier nicht? Wenn ich null
referToSample zuweise, sollte sample ebenfalls null sein und eine NullPointerException auslösen, aber es wird keine ausgelöst. Warum?
quelle
sample
ist immer nochsample
. Du hast dich nur verändertreferToSample
.sample
undreferToSample
als Objekte, aber sie sind keine Objekte, sondern Variablen. Eine Variable kann einen Verweis auf ein Objekt enthalten, ist jedoch selbst kein Objekt. Es ist eine subtile Unterscheidung, aber es ist im Grunde die Essenz Ihrer Verwirrung.volatile
,final
,=
,==
...) bei der Anwendung auf eine Objektvariablen beeinflußt die Zeiger , nicht das Objekt , das es sich bezieht.Antworten:
null
Zuweisungen ändern ihren Wert nicht, indem sie dieses Objekt global zerstören. Diese Art von Verhalten würde zu schwer zu verfolgenden Fehlern und kontraintuitivem Verhalten führen. Sie brechen nur diese spezifische Referenz .Nehmen wir das der Einfachheit halber an
sample
auf die Adresse 12345 verwiesen wird. Dies ist wahrscheinlich nicht die Adresse und wird nur verwendet, um die Dinge hier zu .Die Adresse wird normalerweise mit dem seltsamen Hexadezimalwert in angegeben1Object#hashCode()
, dies ist jedoch implementierungsabhängig.Aus den markierten Linien ergeben sich folgende
See diagram
Diagramme der Objekte:Abbildung 1:
Abbildung 2:
Diagramm 2 zeigt, dass das Annullieren
referToSample
den Verweissample
auf den StringBuilder bei nicht unterbricht00012345
.1 GC-Überlegungen machen dies unplausibel.
quelle
hashCode()
ist nicht dasselbe wie SpeicheradressehashCode
definieren es normalerweise, um einen Wert zurückzugeben, der nichts mit Speicheradressen zu tun hat. Ich denke, Sie können Ihren Standpunkt zu Objektreferenzen im Vergleich zu Objekten äußern, ohne dies zu erwähnenhashCode
. Die Feinheiten, wie man die Speicheradresse erhält, können für einen weiteren Tag belassen werden.Am Anfang war es, wie Sie sagten
referToSample
,sample
wie unten gezeigt:1. Szenario 1:
2. Szenario 1 (Forts.):
Hier, wie
referToSample
es sich bezog,sample
wurde beim Schreiben "B" angehängtreferToSample.append("B")
Das Gleiche geschah in Szenario 2:
Aber in 3. Szenario 3: Wie Hexafraktion sagte,
Wenn Sie zuweisen
null
,referToSample
wann es referenziert hat , hat es den Wertsample
nicht geändert , sondern nur die Referenz von gebrochensample
, und jetzt zeigt es nirgendwo hin . Wie nachfolgend dargestellt:Nun, als
referToSample
Punkte nirgendwo , also während SiereferToSample.append("A");
keine Werte oder Referenzen haben würden, an die es A anhängen kann. Also würde es werfenNullPointerException
.ABER
sample
ist immer noch dasselbe, mit dem Sie es initialisiert habenStringBuilder sample = new StringBuilder();
so wurde es initialisiert, so dass es jetzt A anhängen kann und nicht werfen wirdNullPointerException
quelle
referToSample = sample;
sich auf sample beziehen, kopieren Sie nur die Adresse dessen, worauf verwiesen wirdKurz gesagt: Sie weisen einer Referenzvariablen null zu, nicht einem Objekt.
In einem Beispiel ändern Sie den Status eines Objekts, auf das zwei Referenzvariablen verweisen. In diesem Fall spiegeln beide Referenzvariablen die Änderung wider.
In einem anderen Beispiel ändern Sie die einer Variablen zugewiesene Referenz, dies hat jedoch keine Auswirkungen auf das Objekt selbst. Daher bemerkt die zweite Variable, die sich immer noch auf das ursprüngliche Objekt bezieht, keine Änderung des Objektstatus.
Zu Ihren spezifischen "Regeln":
Sie beziehen sich erneut auf das Ändern des Status des einen Objekts, auf das sich beide Variablen beziehen.
Auch hier ändern Sie die Referenz einer Variablen, was absolut keine Auswirkung auf die Referenz der anderen Variablen hat.
Dies sind zwei völlig unterschiedliche Aktionen, die zu zwei völlig unterschiedlichen Ergebnissen führen.
quelle
Siehe dieses einfache Diagramm:
Wenn Sie einen Anruf Methode auf
referToSample
, dann[your object]
wird aktualisiert, so dass es wirkt sichsample
auch. Aber wenn Sie sagenreferToSample = null
, dann ändern Sie einfach, worauf sichreferToSample
bezieht .quelle
Hier verweisen 'sample' und 'referToSample' auf dasselbe Objekt. Dies ist das Konzept eines unterschiedlichen Zeigers, der auf denselben Speicherort zugreift. Das Zuweisen einer Referenzvariablen zu null zerstört das Objekt also nicht.
bedeutet, dass 'referToSample' nur auf null zeigt, das Objekt gleich bleibt und andere Referenzvariablen einwandfrei funktionieren. Also für 'sample', das nicht auf null zeigt und ein gültiges Objekt hat
funktioniert gut. Wenn wir jedoch versuchen, null an 'referToSample' anzuhängen, wird NullPointException angezeigt. Das ist,
Aus diesem Grund haben Sie in Ihrem dritten Code-Snippet die NullPointerException erhalten.
quelle
Immer wenn ein neues Schlüsselwort verwendet wird, wird ein Objekt auf dem Heap erstellt
1) StringBuilder sample = new StringBuilder ();
2) StringBuilder referToSample = sample;
In 2) wird die Referenz von referSample für dasselbe Objektmuster erstellt
also referToSample = null; ist Nulling Nur die referSample-Referenz hat keine Auswirkung auf das Sample, weshalb Sie dank Javas Garbage Collection keine NULL-Zeigerausnahme erhalten
quelle
Nur einfach, Java hat keine Referenzübergabe. Es übergibt nur eine Objektreferenz.
quelle