J'étais occupé par la mise en œuvre logique du projet en semaine. J'ai eu du temps samedi, alors j'ai sorti une épaisse version anglaise de Thinking in Java de la bibliothèque et lu l'épissage d'objets à cordes. Reportez-vous à ce livre comme une traduction, ajoutez ce que vous pensez et écrivez cet article pour l'enregistrer.
Objet de chaîne immuable
En Java, les objets de chaîne sont immuables (immuables). Dans le code, vous pouvez créer plusieurs alias pour un objet String. Mais les références de ces alias sont les mêmes.
Par exemple, S1 et S2 sont un alias pour les objets "droidyue.com", et les alias sont stockés dans des références à l'objet réel. SO S1 = S2
String S1 = "Droidyue.com"; String S2 = S1; System.out.println ("S1 et S2 a la même référence =" + (S1 == S2));Le seul opérateur surchargé à Java
Dans Java, le seul opérateur surchargé est lié à l'épissage de chaîne. +, + =. En plus de cela, les concepteurs de Java n'autorisent pas la surcharge d'autres opérateurs.
Analyse d'épissage
Y a-t-il vraiment un coût de performance?
Après avoir compris les deux points ci-dessus, vous pouvez avoir de telles pensées. Étant donné que l'objet Sting est immuable, l'épissage de plusieurs chaînes (trois ou plus) produira inévitablement des objets de chaîne intermédiaires inutiles.
String username = "Andy"; String Age = "24"; String Job = "Developer"; String info = Username + Age + Job;
Pour obtenir les informations ci-dessus, le nom d'utilisateur et l'âge seront épissés pour générer un objet de chaîne temporaire T1, avec le contenu d'Andy24, puis T1 et les travaux seront épissés pour générer l'objet info dont nous avons besoin à la fin. Parmi eux, un T1 intermédiaire est généré, et après la création de T1, il ne sera pas recyclé automatiquement, ce qui occupera inévitablement une certaine quantité d'espace. S'il s'agit d'un épisode de beaucoup (en supposant des centaines, plus commun dans l'appel à tostring à l'objet), alors le coût sera plus élevé et les performances seront beaucoup plus faibles.
Traitement d'optimisation du compilateur
Y a-t-il vraiment le coût de performance ci-dessus? L'épissage des cordes est si courant, n'y a-t-il pas d'optimisation spéciale de traitement? La réponse est que cette optimisation est effectuée lorsque le compilateur compile .java en bytecode.
Si un programme Java veut fonctionner, il faudra deux périodes, compilera le temps et le temps d'exécution. Au moment de la compilation, le compilateur Java (compilateur) convertit le fichier java en bytecode. Au moment de l'exécution, la machine virtuelle Java (JVM) exécute le bytecode généré par compilation. Pendant ces deux périodes, Java a atteint la soi-disant compilation et courir partout.
Expérimentons des optimisations faites pendant la période de compilation, et nous créons un morceau de code qui peut avoir des coûts de performance.
classe publique ConcaTENation {public static void main (String [] args) {String username = "Andy"; String Age = "24"; String Job = "développeur"; Chaîne info = nom d'utilisateur + âge + travail; System.out.println (info); }}Compiler la concaténation.java. Obtenir la concaténation.classe
javac concatenation.java
Ensuite, nous utilisons Javap pour décompiler le fichier compilé Concaténation.Class. Concaténation Javap -C. Si la commande Javap n'est pas trouvée, veuillez envisager d'ajouter le répertoire où le Javap est situé à la variable d'environnement ou en utilisant le chemin complet de Javap.
17: 22: 04-androidyue ~ / workspace_adt / strings / src $ javap -c concaténationcompilé de "concatenation.java" classe publique Concaténation {public concatenation (); Code: 0: aload_0 1: invokeSpecial # 1 // Méthode java / lang / objet. "<Init>" :() v 4: return public static void main (java.lang.string []); CODE: 0: LDC # 2 // String Andy 2: Store_1 3: LDC # 3 // String 24 5: Store_2 6: LDC # 4 // STRING Developer 8: Store_3 9: Nouveau # 5 // Classe Java / Lang / StringBuilder 12: Dup 13: InvokEspecial # 6 // Méthode Java / Lang / StringBuilder. invokeVirtual # 7 // Méthode java / lang / stringBuilder.append: (ljava / lang / string;) ljava / lang / stringBuilder; 20: aload_2 21: invokevirtual # 7 // méthode java / lang / stringBuilder.append: (ljava / lang / string;) ljava / lang / stringBuilder; 24: aload_3 25: invokevirtual # 7 // Méthode java / lang / stringBuilder.append: (ljava / lang / string;) ljava / lang / stringBuilder; 28: invokeVirtual # 8 // Méthode java / lang / stringBuilder.tostring :() ljava / lang / string; 31: Store 4 33: GetStatic # 9 // Field Java / Lang / System.out: ljava / io / printStream; 36: ALOAD 4 38: invokevirtual # 10 // méthode java / io / printstream.println: (ljava / lang / string;) v 41: return}Parmi eux, les LDC, les magasins, etc. sont des instructions Java Bytecode, similaires aux instructions d'assemblage. Les commentaires suivants utilisent du contenu lié à Java pour l'explication. Nous pouvons voir qu'il y a de nombreux Builders de String, mais nous les appelons sans affichage dans le code Java. Il s'agit de l'optimisation faite par le compilateur Java. Lorsque le compilateur Java rencontre un épissage de chaîne, il créera un objet StringBuilder. L'épissage derrière elle appelle réellement la méthode d'ajout de l'objet StringBuilder. De cette façon, il n'y aura aucun problème qui nous inquiète.
Optimisation du compilateur seule?
Puisque le compilateur nous a aidés à optimiser, est-il suffisant pour s'appuyer uniquement sur l'optimisation du compilateur? Bien sûr que non.
Regardons un morceau de code qui n'a pas été optimisé pour de faibles performances
public void implicitUSestRingBuilder (String [] valeurs) {String result = ""; for (int i = 0; i <valeurs.length; i ++) {result + = valeurs [i]; } System.out.println (résultat);}Compiler avec Javac et voir avec Javap
11: Nouveau # 5 // Classe Java / Lang / StringBuilder 14: DUP 15: InvokeSpecial # 6 // Méthode Java / Lang / StringBuilder. "<Init>" :() V 18: aload_2 19: InvokeVirtual # 7 // Méthode 31: Store_2 32: Iinc 3, 1 35: GOTO 5 38: Getstatic # 9 // Field java / lang / system.out: ljava / io / printStream; 41: aload_2 42: invokevirtual # 10 // méthode java / io / printstream.println: (ljava / lang / string;) v 45: return
Parmi eux 8: if_icmpge 38 et 35: goto 5 forment une boucle. 8: if_icmpge 38 signifie que si la comparaison entière de la pile d'opérande JVM est supérieure ou égale à (le résultat opposé de i <valeurs.length) est vrai, puis sautez à la ligne 38 (System.out). 35: Goto 5 signifie sauter directement à la ligne 5.
Mais il y a une chose très importante ici que la création d'objets StringBuilder se produit entre les boucles, ce qui signifie que le nombre de fois que les boucles créeront des objets StringBuilder, ce qui n'est évidemment pas bon. Code de bas niveau nu.
Optimisez-le légèrement pour améliorer instantanément la qualité.
public void expliciteStringBuilder (string [] valeurs) {stringBuilder result = new StringBuilder (); for (int i = 0; i <valeurs.length; i ++) {result.append (valeurs [i]); }}Informations compilées correspondantes
public void expliciteStringBuider (java.lang.string []); Code: 0: Nouveau # 5 // Classe Java / Lang / StringBuilder 3: DUP 4: InvokeSpecial # 6 // Méthode Java / Lang / StringBuilder. "<Init>" :() V 7: ASTORE_2 8: iconst_0 9: istore_3 10: ILOAD_3 11: aload_1 12: ArrayLeng 17: Aload_1 18: Iload_3 19: aaload 20: invokevirtual # 7 // Méthode java / lang / stringBuilder.append: (ljava / lang / string;) ljava / lang / stringBuilder; 23: Pop 24: Iinc 3, 1 27: Goto 10 30: Retour
Comme on peut le voir d'en haut, 13: if_icmpge 30 et 27: GOTO 10 Formez une boucle de boucle, tandis que 0: New # 5 est en dehors de la boucle, donc StringBuilder n'est pas créé plusieurs fois.
En général, nous devons essayer d'éviter la création implicite ou explicite de Builders dans le corps de la boucle. Par conséquent, ceux qui comprennent comment le code est compilé et comment il est exécuté en interne a des niveaux de code relativement élevés.
S'il y a des erreurs dans l'article ci-dessus, veuillez les critiquer et les corriger.
Ce qui précède consiste à régler les informations sur l'épissage des chaînes Java, et nous continuerons d'ajouter des informations pertinentes à l'avenir. Merci pour votre soutien pour ce site Web!