11
votes

Comment Java est-elle la concaténation à la chaîne à l'aide de "+"?

J'ai lu à propos de la façon dont Java fonctionne avec + = opérateur, à l'aide de stringbuilder .
Est-ce la même chose avec un ("a" + "b") opération?


1 commentaires

Je vous recommande de consulter ce Excellent article .


6 Réponses :


14
votes

9 commentaires

Il n'est pas garanti que vous créez de nouvelles chaînes chaque fois que vous concatéez; C'est en fait jusqu'au compilateur. Un compilateur de mauvaise qualité se comporterait comme vous décrivez ...


Pas nécessairement. Le compilateur l'optimisera de toute façon. Changez votre règle de règle sur: "Si vous allez utiliser stringa + = stringb , puis utilisez stringbuilder plutôt, car il mangeait effectivement tas. Votre réponse est plus impliquant que vous avez besoin d'un stringbuilder pour chaque stressa + stringb , ce n'est pas vrai.


En fait, il est requis par la JLS que la concaténation de la compilation des constantes de la compilation entraîne une chaîne interne . La règle de base devrait être que si vous allez créer une chaîne dans une boucle et il y a une chance de tout ce qu'elle bouclera un certain nombre de fois, l'utilisation d'un stringbuilder . Aucun point dans la complication du code de concaténation linéaire avec StirngBuilder .


Non seulement les littéraux de chaîne concaténés avec + sont modifiés à une seule chaîne lors de la compilation (dans votre exemple, le compilateur le simplifierait à la chaîne C = "AB";), le compilateur peut également optimiser la concaténation avec + pour utiliser un StringBuilder . Vous ne devriez vraiment pas utiliser StringBuilder pour plus de complexité ajoutée, comme lors de l'annexe dans une boucle.


Se mettre d'accord. Avec vous tous. Vient d'essayer de le garder simple. Je pense que les questions demandent une réponse générale générale, une réponse comprenant des cas où "A" + "B" peut également être STRA + STRB.


@Colind: Il ne peut que "optimiser"-la des contraintes très étroites. Par exemple, une boucle de concaténation se traduira par une nouvelle chaîne sur chaque boucle; Le stringbuilder n'est pas utilisé de manière optimale automatiquement. Bien sûr, cela ne compte vraiment que pour de très grandes boucles ou boucles impliquant de très grandes chaînes.


@ T.J. Crowder Oui, je sais que cela ne fait pas de bonnes choses avec des boucles, c'est pourquoi je les ai mentionnés comme cas pour utiliser StressBuilder directement.


-1: Plus je regarde votre réponse, plus je reçois confus. Les cas pour + sont littéraux, littéraux et quelque chose avec des non-littéraux. Le compilateur peut (et devrait) optimiser le cas des littéraux (mais pas dans certains cas, ce qui est un compilateur Problème de qualité) et dans l'autre cas émettent un stringbuilder (ou Stringbuffer dans les premières versions de Java) en interne. Dans des cas complexes (par exemple, concat dans une boucle) Il est préférable d'écrire tout à la main.


(Le problème de qualité du compilateur est vraiment un défaut de tirer parti de l'associativité de + BTW)



5
votes

Oui, c'est la même chose, mais le compilateur peut éventuellement optimiser les concaténations de littéraux avant de délivrer le code, donc "A" + "B" peut être lancé comme "AB" directement.


2 commentaires

Nope ils ne sont pas les mêmes; Comment peuvent-ils être - concaténation avec des chaînes immuables et une concaténation avec builère à cordes? @Pablo Santa Cruz fournit une réponse digne.


@ Phoenix24: En fait, il scoule de déchets stupides précisément car il ne différencie pas entre la concaténation littérale et la concessive non littérale.



-2
votes

Les chaînes sont plus communément concaténées avec l'opérateur +, comme dans "bonjour," + "monde" + "!"

Source


1 commentaires

Oui, mais je pense qu'il veut dire, comment le compilateur fait-il cette opération? (Et la réponse est en effet qu'il utilise un stringbuilder sous-couvertures.)



37
votes

Si vous combinez littéral em> strings (littéralement "foo" + "bar" code>), le compilateur le fait à la compilation, pas au moment de l'exécution.

Si Vous avez deux chaînes non littérales et les rejoindre avec + code>, le compilateur (Sun's, quand même) utilisera un StringBuilder code> sous les couvertures, mais pas nécessairement de la manière la plus efficace. . Donc, par exemple, si vous avez ceci: p>

Compiled from "SBTest.java"
public class SBTest extends java.lang.Object{
public SBTest();
Code:
   0: aload_0
   1: invokespecial  #1; //Method java/lang/Object."<init>":()V
   4: return

public static final void main(java.lang.String[]);
Code:
   0: getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   3: new   #3; //class SBTest
   6: dup
   7: invokespecial  #4; //Method "<init>":()V
   10: ldc   #5; //String testing
   12: iconst_4
   13: invokevirtual  #6; //Method repeat:(Ljava/lang/String;I)Ljava/lang/String;
   16: invokevirtual  #7; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   19: iconst_0
   20: invokestatic   #8; //Method java/lang/System.exit:(I)V
   23: return

java.lang.String repeat(java.lang.String, int);
Code:
   0: iload_2
   1: ifgt  7
   4: ldc   #9; //String
   6: areturn
   7: aload_1
   8: astore_3
   9: iinc  2, -1
   12: iload_2
   13: ifle  38
   16: new   #10; //class java/lang/StringBuilder
   19: dup
   20: invokespecial  #11; //Method java/lang/StringBuilder."<init>":()V
   23: aload_3
   24: invokevirtual  #12; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   27: aload_1
   28: invokevirtual  #12; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   31: invokevirtual  #13; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   34: astore_3
   35: goto  9
   38: aload_3
   39: areturn

}


2 commentaires

@Tom Brito: En fait, sur la base de la question, je ne suis pas sûr que la réponse à un mot serait "oui" ou "non" alors j'ai pris cela et j'ai juste expliqué ce qui se passe. :-)


@ T.J.Crowder You Rock !! (Je sais que ce n'est pas un commentaire recommandé ... Je ne pouvais pas résister: p)



4
votes

Pour concaténer un nombre fixe de chaînes dans une expression avec + , le compilateur produira du code à l'aide d'un seul StringBuilder .

. Par exemple La ligne xxx

donne le même bytecode que la ligne xxx

Lors de la compilée à l'aide du compilateur Javac. (Le compilateur Eclipse produit un code un peu plus optimisé en invoquant Nouveau StringBuilder (a) , enregistrant ainsi un appel de méthode.)

Comme mentionné dans d'autres réponses, le compilateur concaténera les littéraux de chaînes Comme "a" + "b" dans une chaîne elle-même, produisant ByTecode contenant "AB" à la place.

Comme mentionné partout sur le net, Vous ne devez pas utiliser + pour construire une chaîne dans une boucle , car vous copiez le début de la chaîne sur et sur de nouvelles chaînes. Dans cette situation, vous devez utiliser un stringbuilder que vous déclarez en dehors de la boucle.


0 commentaires

0
votes

"a" + "b" opération

Bien que lisible, facile à formater et directement en avant, des chaînes concaténantes avec "+" sont considérées comme mauvaises dans Java.

Chaque fois que vous appendez quelque chose via '+' (string.concat ()) une nouvelle chaîne est créée, l'ancien contenu de chaîne est copié, le nouveau contenu est ajouté et l'ancienne chaîne est supprimée. Plus la corde gagne plus longtemps qu'il faut - il y a plus de copier et plus de déchets sont produits. NOTE: Si vous ne faites que concaténer quelques cordes (disons 3,4) et ne pas construire une chaîne via une boucle ou simplement écrire une application de test, vous pouvez toujours rester avec "+"

Utilisation stringbuilder

Lors de la manipulation étendue de chaîne (ou à l'annexe via une boucle), remplacez "+" avec stringbuilder .append est probablement recommandé. Les objets intermédiaires mentionnés en cas de "+" ne sont pas créés au cours de APPEND () METHODE Call.

Il convient également de noter que les optimisations du compilateur Sun Java, qui crée automatiquement stringbuilders ( Stringbuffers <5.0) quand il voit des concatuations de chaîne. Mais c'est juste le compilateur Java Sun.


0 commentaires