Der Wert des von der Java-Methode behandelten Arguments wird als Wert für den Basistyp und als Referenz für den Referenztyp übergeben. Wenn diese Geschichte herauskommt, gibt es jedoch einige Fragen, bei denen ich das Verhalten von String nicht verstehe.
Nun, ich wünschte ich könnte das erklären.
Für den Basistyp wird der Wert übergeben. Der Wert wird also kopiert und übergeben. Der Wert selbst wird nicht übergeben. Dies bedeutet, dass sich der Wert der übergebenen Variablen vor und nach der Übergabe an die Methode nicht ändert.
//Beispiel 1
public class PrimitiveType {
public static void main(String[] args) {
PrimitiveSample ps = new PrimitiveSample();
int i = 5;
System.out.println("Wert vor Änderung der Hauptmethode: " + i);
ps.changeInt(i);
System.out.println("Wert nach Änderung der Hauptmethode: " + i);
}
}
class PrimitiveSample {
public int changeInt(int i) {
System.out.println("Wert vor Änderung mit changeInt: " + i);
i = i + 10;
System.out.println("Wert nach Änderung mit changeInt: " + i);
return i;
}
}
Wert vor Änderung der Hauptmethode: 5
Wert vor Änderung mit changeInt: 5
Wert nach Änderung mit changeInt: 15
Wert nach Änderung der Hauptmethode: 5
Im Fall des Referenztyps handelt es sich tatsächlich um "Wert übergeben", da "die Referenzadresse des Referenztyps kopiert und übergeben wird".
Mit anderen Worten, wenn Sie ein Memo mit "Adresse von 1 Sakuragaoka-cho, Shibuya-ku, Tokio" kopieren und übergeben und die Kopie des Memos verwenden, um "einen Brief an die Adresse von 1 Sakuragaoka-cho, Shibuya-ku, Tokio" zu senden. "Adresse von 1 Sakuragaoka-cho, Shibuya-ku, Tokio" erhält den Brief. Selbst wenn Sie die Kopie des Memos zerreißen, hat dies keine Auswirkungen auf die "Adresse von 1 Sakuragaoka-cho, Shibuya-ku, Tokio".
//Beispiel 2
public class PointerType {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer();
sb.append("AIUEO");
System.out.println("Wert vor Änderung der Hauptmethode: " + sb.toString());
PointerSample ps = new PointerSample();
ps.appendData(sb);
System.out.println("Wert vor Änderung der Hauptmethode: " + sb.toString());
ps.deleteObject(sb);
System.out.println("Das Objekt der Hauptmethode verschwindet nicht: " + sb.toString());
}
}
class PointerSample {
public void appendData(StringBuffer sb) {
System.out.println("Wert vor Änderung in appendData: " + sb.toString());
sb.append("Kakikukeko");
System.out.println("Wert nach Änderung mit appendData: " + sb.toString());
}
public void deleteObject(StringBuffer sb) {
sb = null;
}
}
Wert vor Änderung der Hauptmethode:AIUEO
Wert vor Änderung in appendData:AIUEO
Wert nach Änderung mit appendData:Aiue Okakikukeko
Wert vor Änderung der Hauptmethode:Aiue Okakikukeko
Das Objekt der Hauptmethode verschwindet nicht:Aiue Okakikukeko
Ich denke, wir haben bisher darüber gesprochen. Erstens ist das Wort "Referenzübergabe" nicht gut, und "Wertübergabe des Referenzziels" ist korrekt, und es gibt andere Personen, die dies sagen. Ich weiß nicht viel über Java, aber als ich jemanden fragte, der gut in C und C ++ ist, erklärte er: "Dies ist von Wert." Es ist interessant.
Wenn also String oder Integer herauskommt, gibt es ein mysteriöses Argument: "Obwohl der Referenztyp als Referenz übergeben wird, ändert sich der Wert von String nicht. Dies wird als Wert übergeben", wobei jedoch zunächst die obige Geschichte berücksichtigt wird Alles endet mit "Übergeben des Referenztyps als Wert des Referenzziels".
Um noch ein bisschen weiter zu gehen und zu erklären ** Der String-Typ hat keine Funktion zum Ändern des Objekts selbst **, er wird als Konstante behandelt. Gleich wie Integer-Typ. Es gibt keine Funktion zum Ändern des Objekts. Es gibt keine Funktion wie List oder StringBuffer, die "Ihrem Objekt einen Wert hinzufügt und den Inhalt des Objekts ändert".
//Beispiel 3, das nicht aktualisiert wird
public class StringType {
public static void main(String[] args) {
StringSample ss = new StringSample();
String str = "AIUEO";
System.out.println("Wert vor Änderung der Hauptmethode: " + str);
ss.changeString(str);
System.out.println("Wert nach Änderung der Hauptmethode: " + str);
}
}
class StringSample {
public void changeString(String str) {
System.out.println("Wert vor Änderung mit changeString: " + str);
str = str + "Kakikukeko";
System.out.println("Wert nach Änderung mit changeString: " + str);
}
}
Wert vor Änderung der Hauptmethode:AIUEO
Wert vor Änderung mit changeString:AIUEO
Wert nach Änderung mit changeString:Aiue Okakikukeko
Wert nach Änderung der Hauptmethode:AIUEO
Wenn Sie nur Beispiel 3 betrachten, sieht es genauso aus wie Beispiel 1 und Sie sagen "Wert übergeben".
Tatsächlich müssen Sie den Inhalt von str = str +" Kakikukeko ";
überprüfen.
System.identityHashCode (obj) ist nicht universell einsetzbar, kann jedoch für diese Forschungsstufe verwendet werden. Wenn Sie versuchen, es in Ihr Unternehmen zu integrieren, müssen Sie berücksichtigen, dass "möglicherweise Duplikate vorliegen". Wenn sich der Wert jedoch ändert, ist es gut zu sehen, dass sich das Objekt selbst geändert hat.
public class StringType {
public static void main(String[] args) {
StringSample ss = new StringSample();
String str = "AIUEO";
System.out.println("Wert vor Änderung der Hauptmethode: " + str);
System.out.println("Hash 1 in main:" + System.identityHashCode(str));
ss.changeString(str);
System.out.println("Wert nach Änderung der Hauptmethode: " + str);
System.out.println("Hash 2 in main:" + System.identityHashCode(str));
}
}
class StringSample {
public void changeString(String str) {
System.out.println("-------");
System.out.println("Wert vor Änderung mit changeString: " + str);
System.out.println("Hash 1 in changeString:" + System.identityHashCode(str));
System.out.println("-------");
str = str + "Kakikukeko";
System.out.println("Wert nach Änderung mit changeString: " + str);
System.out.println("Hash 2 in changeString:" + System.identityHashCode(str));
System.out.println("-------");
}
}
Wert vor Änderung der Hauptmethode:AIUEO
Hash 1 in main:2018699554
-------
Wert vor Änderung mit changeString:AIUEO
Hash 1 in changeString:2018699554
-------
Wert nach Änderung mit changeString:Aiue Okakikukeko
Hash 2 in changeString:1311053135
-------
Wert nach Änderung der Hauptmethode:AIUEO
Hash 2 in main:2018699554
Der Haupt-Hash ist "2018699554", aber in changeString gibt es "2018699554" und "1311053135". Wenn sich das Argument str nicht ändert, entspricht es dem Hash-Wert in main, aber das Objekt hat sich geändert, wenn der str-Wert geändert wird.
Mit anderen Worten, anstatt vom ursprünglichen "2018699554" zu wechseln, haben wir ein neues Objekt "1311053135" erstellt und dort auf "Aiue Okakikukeko" verwiesen.
Dies ist dasselbe wie in Beispiel 2, "Brechen einer Kopie eines Memos". In Bezug auf str ist es nur der Unterschied zwischen "Einfügen von Null" und "Einfügen eines neuen Objekts".
Wenn der String-Typ eine Methode wie "Ändern des Werts seines eigenen Objekts" hätte, wäre dies möglicherweise keine so verwirrende Kontroverse gewesen. Umgekehrt gilt für den String-Typ auch, dass ein einmal festgelegtes Objekt unveränderlich ist, bis ein anderes Objekt zugewiesen wird.
Ich weine manchmal, wenn ich sage, dass ein Array ein Array vom Typ int ist, daher muss es als Wert übergeben werden. Da ein Array jedoch ein reales Objekt ist, ist es gut, es genauso zu betrachten wie andere Referenztypen. Ich denke nicht, dass es so schwierig ist, wenn Sie sich den Grundtyp als eine Schachtel mit Objekten vorstellen, die hineingelegt werden können.
Das Übergeben als Referenz ist nicht gut, da das Bild so aussieht, als würde der Referenzwert des Objekts selbst übergeben. Es war eine Geschichte.
Recommended Posts