L'histoire de ne pas connaître le comportement de String en passant par Java

Qu'est-ce que Java Pass by Reference?

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

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

Passer par référence

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.

Chaîne ou entier ...

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é.

Arrangement ... vous ...

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.

À la fin

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

L'histoire de ne pas connaître le comportement de String en passant par Java
L'histoire de la comparaison de chaînes de bas niveau en Java
[Java] Le mot passant par référence est mauvais!
[Édition Java] Histoire de la sérialisation
Histoire du passage de Java Gold SE8
L'histoire reçue par Java SE11 silver
L'histoire de l'écriture de Java dans Emacs
[Java] [Spring] Tester le comportement de l'enregistreur
[Java] L'histoire selon laquelle le tableau attendu n'a pas été obtenu par la méthode String.split.
L'histoire de la fabrication d'un Othello ordinaire à Java
L'histoire de l'apprentissage de Java dans la première programmation
[Java] Obtenir la longueur de la chaîne de paire de substitution
[Java] La partie déroutante de String et StringBuilder
[Note] Java: mesure la vitesse de concaténation de chaînes
[Java] Résumé de base de Java non couvert par Progate ~ Partie 1 ~
Vérifiez le comportement de Java Intrinsic Locks avec bpftrace
Apprenez la signification de «transmettre le PATH» en créant un environnement de développement Java sur Mac
Histoire de passer Java Silver SE8 (programmeur Java certifié Oracle, Silver SE 8)
L'histoire de la création de DTO, semblable à Dao avec Java, SQLite
Je n'ai pas vraiment compris le comportement de Java Scanner et .nextLine ()
À propos de la troncature de String par le nombre d'octets sur Android
20190803_Java & k8s sur Azure L'histoire d'aller au festival
Les débutants en Java ont brièvement résumé le comportement de Array et ArrayList
[Java] Essayez de modifier les éléments de la chaîne Json à l'aide de la bibliothèque
[Java] Résumé de base de Java non couvert par Progate ~ Partie 2 ・ Liste ~
Le piège que l'implémentation par défaut de l'interface Java 8 apporte
Récapitulatif des valeurs renvoyées par la méthode des caractéristiques Spliterator #java
L'histoire de la transmission de Java à Heroku à l'aide du pipeline BitBucket
Gestion de la virgule flottante java Lors de la lecture du livre de référence [Note]
Changer la version de java installée par SDKMAN lors du déplacement de répertoires
Partie 4: Personnalisez le comportement de la connexion OAuth 2.0 prise en charge par Spring Security 5
L'histoire selon laquelle la sortie standard change également fatalement le comportement du programme
L'histoire de toString () commençant par le passage d'un tableau à System.out.println
Une histoire sur l'utilisation de l'API League Of Legends avec JAVA
[Java] Introduction appropriée par Tenpa people Java Part 0 (règles du code)
J'ai essayé de résumer les méthodes de Java String et StringBuilder
L'histoire de l'arrêt parce que le test des rails n'a pas pu être fait
Comment vérifier le contenu de la chaîne de caractères java de longueur fixe
Le comportement de JS fonctionnant sur `Java SE 8 Nashorn` a soudainement changé
[Java] Comparaison d'équivalence où les débutants échouent dans la comparaison de chaînes de caractères. Vous n'êtes peut-être même pas conscient de l'erreur! ??
À propos du comportement de ruby Hash # ==
[Java] Supprimer les éléments de la liste
Diverses méthodes de la classe Java String
[Java] DateTimeFormatter sortie par FormatStyle
L'histoire de @ViewScoped dévore la mémoire
Code de création de chaîne arbitraire par Java
Java passe par valeur et passe par référence
Diverses méthodes de la classe String
[Java] Référence / mise à jour d'Active Directory
Récapitulatif du problème Java "Pass by Reference"
[Java] Comparaison correcte du type String
J'ai lu la source de String
L'origine des expressions Java lambda
L'histoire de la création d'un lanceur de jeu avec une fonction de chargement automatique [Java]
L'histoire de l'acquisition de Java Silver en deux mois de totalement inexpérimenté.
[Java] Comment accéder au début d'une chaîne spécifique à l'aide de la classe String
L'histoire selon laquelle le servlet n'a pas pu être chargé dans l'application Web Java
Vérifiez l'enregistrement MX de l'adresse e-mail avec java et vérifiez le domaine
[Java] Vérifiez si la chaîne de caractères est composée uniquement de blancs (= Vierge)
<Java> Quiz pour convertir par lots les noms de fichiers séparés par une chaîne de caractères spécifique avec une partie du nom de fichier