La valeur de l'argument géré par la méthode Java est passée par valeur pour le type de base et passée par référence pour le type de référence. Cependant, lorsque cette histoire revient, il y a des questions sur lesquelles je ne comprends pas le comportement de String.
Eh bien, j'aimerais pouvoir expliquer cela.
Pour le type de base, il est passé par valeur. La valeur est donc copiée et transmise. Il ne transmet pas la valeur elle-même. Cela signifie que la valeur de la variable transmise ne change pas avant et après sa transmission à la méthode.
//Exemple 1
public class PrimitiveType {
public static void main(String[] args) {
PrimitiveSample ps = new PrimitiveSample();
int i = 5;
System.out.println("Valeur avant changement de méthode principale: " + i);
ps.changeInt(i);
System.out.println("Valeur après modification de la méthode principale: " + i);
}
}
class PrimitiveSample {
public int changeInt(int i) {
System.out.println("Valeur avant changement avec changeInt: " + i);
i = i + 10;
System.out.println("Valeur après modification avec changeInt: " + i);
return i;
}
}
Valeur avant changement de méthode principale: 5
Valeur avant changement avec changeInt: 5
Valeur après modification avec changeInt: 15
Valeur après modification de la méthode principale: 5
Dans le cas d'un type référence, il s'agit en fait de "passage par valeur" car il "copie et passe l'adresse référencée du type référence".
En d'autres termes, si vous copiez et remettez un mémo avec "Adresse du 1 Sakuragaoka-cho, Shibuya-ku, Tokyo" et utilisez la copie du mémo pour "Envoyez une lettre à l'adresse du 1 Sakuragaoka-cho, Shibuya-ku, Tokyo" , "Adresse du 1 Sakuragaoka-cho, Shibuya-ku, Tokyo" recevra la lettre. Cependant, même si vous déchirez la copie du mémo, cela n'affectera pas "l'adresse du 1 Sakuragaoka-cho, Shibuya-ku, Tokyo".
//Exemple 2
public class PointerType {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer();
sb.append("AIUEO");
System.out.println("Valeur avant changement de méthode principale: " + sb.toString());
PointerSample ps = new PointerSample();
ps.appendData(sb);
System.out.println("Valeur avant changement de méthode principale: " + sb.toString());
ps.deleteObject(sb);
System.out.println("L'objet de la méthode principale ne disparaît pas: " + sb.toString());
}
}
class PointerSample {
public void appendData(StringBuffer sb) {
System.out.println("Valeur avant modification dans appendData: " + sb.toString());
sb.append("Kakikukeko");
System.out.println("Valeur modifiée par appendData: " + sb.toString());
}
public void deleteObject(StringBuffer sb) {
sb = null;
}
}
Valeur avant changement de méthode principale:AIUEO
Valeur avant modification dans appendData:AIUEO
Valeur modifiée par appendData:Aiue Okakikukeko
Valeur avant changement de méthode principale:Aiue Okakikukeko
L'objet de la méthode principale ne disparaît pas:Aiue Okakikukeko
Jusqu'à présent, je pense que nous en avons parlé jusqu'à présent. En premier lieu, le mot «passer par référence» n'est pas bon, et «passer par valeur de la destination de référence» est correct, et il y a d'autres personnes qui le disent. Je ne sais pas grand-chose sur Java, mais quand j'ai demandé à quelqu'un qui était bon en C et C ++, il a déclaré: "C'est par valeur." c'est intéressant.
Ainsi, lorsque String ou Integer sort, il y a un mystérieux argument selon lequel "Bien que le type de référence soit passé par référence, la valeur de String ne change pas. Ceci est passé par valeur", mais en considérant l'histoire ci-dessus en premier lieu Tout se termine par "passer le type de référence par valeur de la destination de référence".
Pour aller un peu plus loin et expliquer ** Le type de chaîne n'a pas de fonction pour changer l'objet lui-même **, il est traité comme une constante. Identique au type Integer. Il n'y a pas de fonction pour changer l'objet lui-même. Il n'y a pas de fonction comme List ou StringBuffer qui "ajoute une valeur à votre objet et modifie le contenu de l'objet".
//Exemple 3 qui n'est pas rafraîchissant
public class StringType {
public static void main(String[] args) {
StringSample ss = new StringSample();
String str = "AIUEO";
System.out.println("Valeur avant changement de méthode principale: " + str);
ss.changeString(str);
System.out.println("Valeur après modification de la méthode principale: " + str);
}
}
class StringSample {
public void changeString(String str) {
System.out.println("Valeur avant modification avec changeString: " + str);
str = str + "Kakikukeko";
System.out.println("Valeur après modification avec changeString: " + str);
}
}
Valeur avant changement de méthode principale:AIUEO
Valeur avant modification avec changeString:AIUEO
Valeur après modification avec changeString:Aiue Okakikukeko
Valeur après modification de la méthode principale:AIUEO
Si vous ne regardez que l'exemple 3, il ressemblera à l'exemple 1 et vous direz «passer par valeur».
En fait, vous devez vérifier le contenu de str = str +" Kakikukeko ";
.
System.identityHashCode (obj) n'est pas polyvalent, mais il peut être utilisé pour ce niveau de recherche. Si vous essayez de l'intégrer dans votre entreprise, vous devez garder à l'esprit qu '«il peut y avoir duplication», mais si la valeur change, il est bon de voir que l'objet lui-même a changé.
public class StringType {
public static void main(String[] args) {
StringSample ss = new StringSample();
String str = "AIUEO";
System.out.println("Valeur avant changement de méthode principale: " + str);
System.out.println("Hash 1 en main:" + System.identityHashCode(str));
ss.changeString(str);
System.out.println("Valeur après modification de la méthode principale: " + str);
System.out.println("Hash 2 en main:" + System.identityHashCode(str));
}
}
class StringSample {
public void changeString(String str) {
System.out.println("-------");
System.out.println("Valeur avant modification avec changeString: " + str);
System.out.println("Hash 1 dans changeString:" + System.identityHashCode(str));
System.out.println("-------");
str = str + "Kakikukeko";
System.out.println("Valeur après modification avec changeString: " + str);
System.out.println("Hash 2 dans changeString:" + System.identityHashCode(str));
System.out.println("-------");
}
}
Valeur avant changement de méthode principale:AIUEO
Hash 1 en main:2018699554
-------
Valeur avant modification avec changeString:AIUEO
Hash 1 dans changeString:2018699554
-------
Valeur après modification avec changeString:Aiue Okakikukeko
Hash 2 dans changeString:1311053135
-------
Valeur après modification de la méthode principale:AIUEO
Hash 2 en main:2018699554
Le hachage principal est "2018699554", mais dans changeString il y a "2018699554" et "1311053135". S'il n'y a pas de changement dans l'argument str, il correspond à la valeur de hachage dans main, mais l'objet a changé lorsque la valeur str est modifiée.
En d'autres termes, au lieu d'apporter des modifications à l'original «2018699554», nous avons créé un nouvel objet «1311053135» et y avons fait référence à «Aiue Okakikukeko».
C'est la même chose que dans l'exemple 2, "Rompre une copie d'un mémo". En termes de str, ce n'est que la différence entre "insérer null" et "insérer un nouvel objet".
Si le type String avait une méthode comme "changer la valeur de son propre objet", cela n'aurait peut-être pas été une controverse aussi déroutante. Inversement, le type String considère également qu'un objet une fois défini est invariant jusqu'à ce qu'un autre objet soit affecté.
Je pleure parfois quand je dis qu'un tableau est un tableau de type int, il doit donc être passé par valeur, mais comme un tableau est un objet réel, il est préférable de le traiter comme tout autre type de référence. Je ne pense pas que ce soit si difficile si vous considérez le type de base comme une boîte d'objets qui peuvent être placés à l'intérieur.
Passer par référence n'est pas bon car cela donne l'impression que l'image passe la valeur de référence de l'objet lui-même. C'était une histoire.
Recommended Posts