Ich weiß, dass dies wahrscheinlich sehr dumm ist, aber viele Orte behaupten, dass die Integer-Klasse in Java unveränderlich ist, aber der folgende Code:
Integer a=3;
Integer b=3;
a+=b;
System.out.println(a);
Kann problemlos ausgeführt werden, um das (erwartete) Ergebnis 6 zu erhalten. Der Wert von a hat sich also effektiv geändert. Bedeutet das nicht, dass Integer veränderlich ist? Sekundäre Frage und ein wenig offtopic: "Unveränderliche Klassen brauchen keine Kopierkonstruktoren". Möchte jemand erklären warum?
java
immutability
mutable
K.Steff
quelle
quelle
Antworten:
Unveränderlich bedeutet nicht, dass
a
niemals ein anderer Wert erreicht werden kann. Ist zum Beispiel auchString
unveränderlich, aber ich kann das trotzdem tun:str
wurde nicht geändert, sondernstr
ist jetzt ein völlig neu instanziiertes Objekt, so wie esInteger
ist. Der Wert vona
mutierte also nicht, sondern wurde durch ein völlig neues Objekt ersetzt, dnew Integer(6)
. H.quelle
+=
Operation instanziiert wurde .Integer.valueOf(int)
und diese Methode verwaltet einen Cache vonInteger
Objekten. Das Ergebnis+=
einerInteger
Variablen könnte also ein Objekt sein, das zuvor existiert hat (oder es könnte sogar dasselbe Objekt sein ... im Fall vona += 0
).a
ist ein "Verweis" auf eine Ganzzahl (3), Ihre Kurzschrifta+=b
bedeutet wirklich, dies zu tun:Also nein, Ganzzahlen sind nicht veränderbar, aber die Variablen, die auf sie zeigen, sind *.
* Es ist möglich, unveränderliche Variablen zu haben. Diese werden mit dem Schlüsselwort gekennzeichnet
final
, was bedeutet, dass sich die Referenz möglicherweise nicht ändert.quelle
Sie können feststellen, dass sich das Objekt mithilfe von geändert hat
System.identityHashCode()
(Ein besserer Weg ist die Verwendung von plain, es ist==
jedoch nicht so offensichtlich, dass sich die Referenz und nicht der Wert geändert hat).druckt
Sie können sehen, dass sich die zugrunde liegende "ID" des Objekts,
a
auf das verwiesen wird, geändert hat.quelle
Auf die erste Frage gestellt,
Die Ganzzahl ist unveränderlich. Was oben passiert ist, ist, dass 'a' in eine neue Referenz von Wert 6 geändert wurde. Der Anfangswert 3 hat keine Referenz im Speicher (er wurde nicht geändert), sodass er mit Müll gesammelt werden kann.
Wenn dies bei einem String passiert, bleibt er länger im Pool (im PermGen-Bereich) als die Ganzzahlen, da er Referenzen erwartet.
quelle
Ja Integer ist unveränderlich.
A ist eine Referenz, die auf ein Objekt zeigt. Wenn Sie ein + = 3 ausführen, wird A neu zugewiesen, um auf ein neues Integer-Objekt mit einem anderen Wert zu verweisen.
Sie haben das ursprüngliche Objekt nie geändert, sondern den Verweis auf ein anderes Objekt gerichtet.
Lesen Sie mehr über den Unterschied zwischen Objekten und Referenzen hier .
quelle
Unveränderlich bedeutet nicht, dass Sie den Wert für eine Variable nicht ändern können. Es bedeutet nur, dass jede neue Zuweisung ein neues Objekt erstellt (ihm einen neuen Speicherort zuweist) und ihm dann der Wert zugewiesen wird.
Um dies selbst zu verstehen, führen Sie eine Ganzzahlzuweisung in einer Schleife durch (wobei die Ganzzahl außerhalb der Schleife deklariert ist) und sehen Sie sich die Live-Objekte im Speicher an.
Der Grund, warum der Kopierkonstruktor für unveränderliche Objekte nicht benötigt wird, ist der einfache gesunde Menschenverstand. Da bei jeder Zuweisung ein neues Objekt erstellt wird, erstellt die Sprache technisch bereits eine Kopie, sodass Sie keine weitere Kopie erstellen müssen.
quelle
Der Grund ist, dass es selten notwendig ist, eine Instanz einer unveränderlichen Klasse zu kopieren (oder sogar zu kopieren). Die Kopie des Objekts sollte "dieselbe" wie das Original sein, und wenn es dieselbe ist, sollte es nicht erforderlich sein, es zu erstellen.
Es gibt jedoch einige zugrunde liegende Annahmen:
Es wird davon ausgegangen, dass Ihre Anwendung der Objektidentität von Instanzen der Klasse keine Bedeutung beimisst.
Es wird davon ausgegangen, dass die Klasse überladen ist
equals
undhashCode
dass eine Kopie einer Instanz nach diesen Methoden "dieselbe" wie das Original ist.Eine oder beide dieser Annahmen könnten falsch sein, und dies könnte die Hinzufügung eines Kopierkonstruktors rechtfertigen.
quelle
So verstehe ich unveränderlich
Wenn int mutieren könnte, würde "a" 8 ausgeben, aber nicht, weil es unveränderlich ist, deshalb ist es 3. Ihr Beispiel ist nur eine neue Zuweisung.
quelle
Ich kann klarstellen, dass Integer (und andere seiner Glaubensbekenntnisse wie Float, Short usw.) durch einfachen Beispielcode unveränderlich sind:
Das Ergebnis ist Hi There 100 anstelle des erwarteten Ergebnisses (wenn sb und i veränderbare Objekte sind) Hi There 1000
Dies zeigt, dass das von i in main erstellte Objekt nicht geändert wird, während sb geändert wird.
StringBuilder zeigte also veränderliches Verhalten, aber keine Ganzzahl.
Integer ist also unveränderlich. Daher bewiesen
quelle
private void doStringBuilder(StringBuilder sb){ sb = new StringBuilder(); }
dannsb
ist unverändert.private void doInteger(Integer i){ System.out.println( i == 100 ); i=1000; System.out.println( i == 100 ); }
Ausgabe ist:
Hallo Tschüss 1000 5000 1000 5000 d a
Char ist also veränderlich, String Integer und int sind unveränderlich.
quelle