J'ai l'habitude de faire ce qui suit dans C
:
void main() {
String zText = "";
fillString(zText);
printf(zText);
}
void fillString(String zText) {
zText += "foo";
}
Et le résultat est:
foo
Cependant, en Java, cela ne semble pas fonctionner. Je suppose parce que l' String
objet est copié au lieu de passer par référencé . Je pensais que les chaînes étaient des objets, qui sont toujours passés par référence.
Qu'est-ce qui se passe ici?
java
string
pass-by-reference
Soren Johnson
la source
la source
Réponses:
Vous avez trois options:
Utilisez un StringBuilder:
Créez une classe de conteneur et transmettez une instance du conteneur à votre méthode:
Créez un tableau:
Du point de vue des performances, le StringBuilder est généralement la meilleure option.
la source
StringBuilder
est plus rapides += "..."
car il n'alloue pas de nouveaux objets String à chaque fois. En fait, lorsque vous écrivez du code Java commes = "Hello " + name
, le compilateur génère du code d'octet qui crée unStringBuilder
et appelleappend()
deux fois.En Java, rien n'est passé par référence . Tout est passé par valeur . Les références d'objet sont passées par valeur. De plus, les chaînes sont immuables . Ainsi, lorsque vous ajoutez à la chaîne transmise, vous obtenez simplement une nouvelle chaîne. Vous pouvez utiliser une valeur de retour ou passer un StringBuffer à la place.
la source
Ce qui se passe, c'est que la référence est passée par valeur, c'est-à-dire qu'une copie de la référence est passée. Rien en java n'est passé par référence, et comme une chaîne est immuable, cette affectation crée un nouvel objet chaîne vers lequel pointe maintenant la copie de la référence . La référence d'origine pointe toujours vers la chaîne vide.
Ce serait la même chose pour n'importe quel objet, c'est-à-dire en lui attribuant une nouvelle valeur dans une méthode. L'exemple ci-dessous rend simplement ce qui se passe plus évident, mais concaténer une chaîne est vraiment la même chose.
la source
java.lang.String est immuable.
Je déteste coller des URL, mais https://docs.oracle.com/javase/10/docs/api/java/lang/String.html est essentiel pour que vous puissiez lire et comprendre si vous êtes en java-land.
la source
les objets sont passés par référence, les primitives sont passées par valeur.
La chaîne n'est pas une primitive, c'est un objet et c'est un cas particulier d'objet.
C'est à des fins d'économie de mémoire. Dans JVM, il existe un pool de chaînes. Pour chaque chaîne créée, JVM essaiera de voir si la même chaîne existe dans le pool de chaînes et la pointera s'il y en avait déjà une.
/* PRODUCTION */
le == vérifie l'adresse mémoire (référence), et le .equals vérifie le contenu (valeur)
la source
Tous les arguments en Java sont passés par valeur. Lorsque vous transmettez un
String
à une fonction, la valeur transmise est une référence à un objet String, mais vous ne pouvez pas modifier cette référence et l'objet String sous-jacent est immuable.La tâche
est équivalent à:
Autrement dit, il réaffecte (localement) le paramètre en
zText
tant que nouvelle référence, qui pointe vers un nouvel emplacement mémoire, dans lequel se trouve un nouveauString
qui contient le contenu d'origine dezText
avec"foo"
appended.L'objet d'origine n'est pas modifié et la
main()
variable locale de la méthodezText
pointe toujours vers la chaîne d'origine (vide).imprime:
Si vous souhaitez modifier la chaîne, vous pouvez, comme indiqué, utiliser
StringBuilder
ou bien un conteneur (un tableau ou uneAtomicReference
classe de conteneur ou une classe de conteneur personnalisée) qui vous donne un niveau supplémentaire d'indirection de pointeur. Sinon, renvoyez simplement la nouvelle valeur et attribuez-la:imprime:
C'est probablement la solution la plus semblable à Java dans le cas général - voir l' élément Java efficace «Favoriser l'immuabilité».
Comme indiqué, cependant,
StringBuilder
vous donnera souvent de meilleures performances - si vous avez beaucoup d'ajout à faire, en particulier dans une boucle, utilisezStringBuilder
.Mais essayez de transmettre immuable
Strings
plutôt que mutableStringBuilders
si vous le pouvez - votre code sera plus facile à lire et plus maintenable. Pensez à créer vos paramètresfinal
et à configurer votre IDE pour vous avertir lorsque vous réaffectez un paramètre de méthode à une nouvelle valeur.la source
String est un objet immuable en Java. Vous pouvez utiliser la classe StringBuilder pour effectuer le travail que vous essayez d'accomplir, comme suit:
Une autre option consiste à créer une classe avec une chaîne comme variable de portée (fortement déconseillée) comme suit:
la source
La réponse est simple. En java, les chaînes sont immuables. Par conséquent, c'est comme utiliser le modificateur 'final' (ou 'const' en C / C ++). Donc, une fois assigné, vous ne pouvez pas le changer comme vous l'avez fait.
Vous pouvez changer qui la valeur à laquelle un des points de chaîne, mais vous ne pouvez pas changer la valeur réelle à laquelle cette chaîne pointe actuellement.
C'est à dire.
String s1 = "hey"
. Vous pouvez faires1 = "woah"
, et c'est tout à fait correct, mais vous ne pouvez pas réellement changer la valeur sous-jacente de la chaîne (dans ce cas: "hey") pour qu'elle soit quelque chose d'autre une fois qu'elle est assignée en utilisant plusEquals, etc. (ie.s1 += " whatup != "hey whatup"
).Pour ce faire, utilisez les classes StringBuilder ou StringBuffer ou d'autres conteneurs mutables, puis appelez simplement .toString () pour reconvertir l'objet en chaîne.
Remarque: les chaînes sont souvent utilisées comme clés de hachage, ce qui explique en partie pourquoi elles sont immuables.
la source
=
sur une référence n'affecte JAMAIS l'objet sur lequel elle pointait, quelle que soit la classe.String est une classe spéciale en Java. C'est Thread Safe, ce qui signifie "Une fois qu'une instance String est créée, le contenu de l'instance String ne sera jamais changé".
Voici ce qui se passe
Tout d'abord, le compilateur Java obtiendra la valeur de l'instance zText String, puis créera une nouvelle instance String dont la valeur est zText en ajoutant "foo". Vous savez donc pourquoi l'instance vers laquelle zText pointe n'a pas changé. C'est une instance totalement nouvelle. En fait, même String "foo" est une nouvelle instance de String. Donc, pour cette instruction, Java créera deux instances String, l'une est "foo", une autre est la valeur de zText append "foo". La règle est simple: la valeur de l'instance String ne sera jamais modifiée.
Pour la méthode fillString, vous pouvez utiliser un StringBuffer comme paramètre, ou vous pouvez le modifier comme ceci:
la source
Les chaînes sont immuables en Java.
la source
Cela fonctionne avec StringBuffer
Encore mieux utiliser StringBuilder
la source
La chaîne est immuable en java. vous ne pouvez pas modifier / changer une chaîne littérale / objet existante.
String s = "Bonjour"; s = s + "salut";
Ici, la référence précédente s est remplacée par les nouvelles références pointant vers la valeur "HelloHi".
Cependant, pour apporter la mutabilité, nous avons StringBuilder et StringBuffer.
StringBuilder s = nouveau StringBuilder (); s.append ("Salut");
ceci ajoute la nouvelle valeur "Hi" aux mêmes références. //
la source
Aaron Digulla a la meilleure réponse à ce jour. Une variante de sa deuxième option consiste à utiliser le wrapper ou la classe de conteneur MutableObject de la bibliothèque commons lang version 3+:
vous enregistrez la déclaration de la classe conteneur. L'inconvénient est une dépendance à la lang lib commune. Mais la lib a beaucoup de fonctions utiles et presque tous les grands projets sur lesquels j'ai travaillé l'ont utilisée.
la source
Pour passer un objet (y compris String) par référence dans java, vous pouvez le passer en tant que membre d'un adaptateur environnant. Une solution avec un générique est ici:
la source
Pour quelqu'un qui est plus curieux
la source