Récemment, lorsque je cherchais un emploi, l'examinateur m'a posé une question simple: "La différence entre StringBuffer et StringBuilder, quels sont leurs scénarios d'application?" La réponse de l'éditeur est partagée avec vous ci-dessous, afin qu'il puisse être pratique pour tout le monde d'apprendre à l'avenir, afin de faire un dossier.
En fait, recherchez simplement le maître Google et vous aurez la réponse: StringBuffer est complètement équivalent aux méthodes et fonctions de StringBuilder, mais la plupart des méthodes de StringBuffer utilisent le mot-clé synchronisé pour la modification, ils sont donc en file d'attente. Sans cette modification, StringBuilder peut être considéré comme un thread-unsafe.
Afin de mieux comprendre la réponse ci-dessus, il est préférable de voir directement que l'implémentation du code source de StringBuffer et StringBuilder est plus réaliste. En tant que programmeur, "Si vous avez des questions, regardez le code source" est la bonne façon. Je peux dire de manière responsable, bien sûr, vous devez avoir des conditions!
Dans l'implémentation de JDK, StringBuffer et StringBuilder sont hérités de AbstractStringBuilder. Pour la sécurité et la non-sécurité du multi-threading, vous aurez une compréhension approximative des méthodes synchronisées dans StringBuffer.
Ici, je parlerai brièvement du principe d'implémentation d'AbstractStringBuilder: nous savons que l'utilisation de StringBuffer n'est rien de plus que d'améliorer l'efficacité de la connexion de chaîne en Java, car si vous utilisez + directement pour la connexion de chaîne, JVM créera plusieurs objets de chaîne, qui provoquera certaines frais généraux. AbstractStringBuilder utilise un tableau char pour enregistrer la chaîne qui doit être ajoutée. Le tableau char a une taille initiale. Lorsque la longueur de la chaîne de la chaîne d'appel dépasse la capacité actuelle du tableau de char, le réseau de char est élargi dynamiquement, c'est-à-dire réapplique un espace mémoire plus grand, puis en copie le tableau de char actuel vers un nouvel emplacement. Parce que les frais généraux de la mémoire et de la copie de réallocation sont relativement importants, chaque fois que vous réappliquez l'espace mémoire est dans la manière dont l'espace mémoire est plus grand que le courant requis, ce qui est 2 fois.
Ensuite, amusez-vous!
Voici quelques informations dans Google:
【
StringBuffer a commencé avec JDK 1.0
StringBuilder a commencé avec JDK 1.5
À partir de JDK 1.5, l'opération de connexion (+) avec des variables de chaîne est utilisée en interne par JVM
StringBuilder est implémenté et cette opération a été implémentée à l'aide de StringBuffer.
】
Nous examinons le processus d'exécution via un programme simple:
Listing 1 buffer.java
classe publique Buffer {public static void main (String [] args) {String s1 = "aaaaa"; String S2 = "BBBBBB"; String r = null; int i = 3694; r = s1 + i + s2; pour (int j = 0; i <10; j ++) {r + = "23124"; }}}Utilisez le tampon Javap -C de commande pour afficher son implémentation bytecode:
Listing 2 bytecode de classe tampon
La liste correspondante 1 et la liste 2, l'instruction LDC dans la liste 2 charge la chaîne "AAAA" du pool constant en haut de la pile, et Istore_1 stocke "AAAAA" en variable 1. Ce qui suit est le même. Sipush pousse une valeur constante entière courte (-32768 ~ 32767) en haut de la pile. Voici la constante "3694". Pour plus d'instructions Java, veuillez consulter un autre article "Ensemble d'instructions Java".
Voyons directement que 13, 13 ~ 17 est nouveau dans un objet StringBuffer et appelez sa méthode d'initialisation. 20 ~ 21 consiste à appuyer d'abord la variable 1 en haut de la pile via Aload_1. Comme mentionné précédemment, la variable 1 est placée dans la string constante "aaaaa", puis appelez la méthode d'ajout de StringBuffer à travers l'instruction invokevirtual pour épisser "aaaaa" ensemble. Les 24 ~ 30 suivants sont les mêmes. Enfin, en 33, la fonction TOSTRING de StringBuffer est appelée pour obtenir le résultat de la chaîne et stockée en variable 3 via le magasin.
Lorsque nous voyons cela, quelqu'un peut dire: "Étant donné que le JVM utilise StringBuffer pour connecter les chaînes, nous n'avons pas besoin d'utiliser STRINGBUFFER nous-mêmes, utilisez simplement" + "Juste!" Est-ce vrai? Bien sûr que non. Comme le dit le proverbe, "il y a une raison de l'existence", continuons à regarder le bytecode correspondant à la boucle suivante.
37 ~ 42 sont tous quelques préparatifs avant d'entrer dans la boucle pour. 37, 38 Set J sur 1. 44 Ici, if_icmpge se compare j avec 10. Si j est supérieur à 10, il sautera directement à 73, c'est-à-dire l'instruction de retour quitte la fonction; Sinon, il entre dans la boucle, c'est-à-dire le bytecode de 47 ~ 66. Ici, nous n'avons qu'à regarder 47 à 51 pour savoir pourquoi nous utilisons StringBuffer dans notre code pour gérer les connexions de chaîne, car chaque fois que nous effectuons l'opération "+", JVM doit à un nouvel objet StringBuffer pour gérer les connexions de chaîne, ce qui sera très coûteux lorsque de nombreuses opérations de connexion de chaîne sont impliquées.