Préface
Cet article présente principalement le contenu pertinent sur l'analyse du code source JDK, StringBuilder et StringBuffer. Il est partagé pour votre référence et votre apprentissage. Je ne dirai pas beaucoup en dessous. Jetons un coup d'œil à l'introduction détaillée ensemble.
Instruction de la classe de chaînes
Classe finale publique String implémente java.io.serializable, comparable <string>, chardence {…}La classe String utilise un modificateur final pour indiquer qu'il ne peut pas être hérité. Dans le même temps, il implémente également trois interfaces, implémentant l'interface sérialisable pour indiquer que la classe de chaîne peut être sérialisée; L'implémentation de l'interface <T> comparable fournit principalement une méthode de comparaison pour comparer les chaînes de chaîne; implémente également l'interface CharSequence, qui représente que Char vaut une séquence lisible (Charbuffer, segment, String, StringBuffer et StringBuilder implémente également l'interface CharSequence)
Chaînes des champs principaux et descriptions d'attribut
/ * Valeur du tableau de caractères, stockant les caractères réels dans la chaîne * / valeur de char finale privée []; / * la valeur de hachage de la valeur par défaut de chaîne 0 * / hash int privé; / * La valeur de hachage de la valeur par défaut de chaîne 0 * // * Un comparateur utilisé pour trier les objets de chaîne, la méthode completoIgnoreCase utilise * / public static final comparateur <string> case_insensitive_order = new CaseInSenSitiveCaparator ();
Analyse de méthode partielle de la chaîne
La classe String fournit une série de constructeurs, et plusieurs d'entre eux ne sont plus recommandés, comme le montre la figure ci-dessous:
Constructeur
Voici les implémentations de deux constructeurs couramment utilisés:
// String str = new String ("123") public String (String original) {this.value = original.value; this.hash = original.hash;} // string str3 = new String (new char [] {'1', '2', '3'}); public string (char de char []) {// copier la valeur du tableau de caractères pour valeur this.value = arrays.copyof (value, value.length); }booléen égaux (objet anobject)
La classe de chaîne remplace la méthode equals pour comparer cette chaîne avec l'objet spécifié. Le résultat est vrai si et seulement si le paramètre n'est pas nul et est un objet de chaîne représentant la même séquence de caractères que cet objet.
Le public booléen est égal (objet anObject) {// comparer les références d'objet directement, et renvoie true if (this == anObject) {return true; } // Comparez la séquence de caractères de l'objet actuel avec une valeur anobject if (anobject instanceof string) {String anotherstring = (string) anObject; int n = value.length; if (n == anotherstring.value.length) {char v1 [] = valeur; char v2 [] = anotherstring.value; int i = 0; while (n--! = 0) {if (v1 [i]! = v2 [i]) return false; i ++; } return true; }} return false; }int compareto (string anothersstring)
Comparez la séquence de caractères de deux chaînes petit à petit. Si un caractère un bit n'est pas le même, renvoyez la différence dans la valeur Unicode des deux caractères de ce bit. Tous les bits sont les mêmes, calculez la différence de longueur des deux cordes. Si les deux chaînes sont les mêmes, retournez 0.
public int compareto (String anotherstring) {int len1 = value.length; int len2 = anotherstring.value.length; // prends la longueur d'une chaîne avec une longueur plus petite int lim = math.min (Len1, Len2); char v1 [] = valeur; char v2 [] = anotherstring.value; int k = 0; tandis que (k <lim) {// compare la valeur de séquence de caractères des deux chaînes une par une. S'il n'est pas égal, renvoyez la différence entre le Unicode des deux caractères à cette position Char C1 = V1 [K]; char c2 = v2 [k]; if (c1! = c2) {return c1 - c2; // renvoie la différence entre Unicode} k ++; } // Tous les bits d'une chaîne plus petite sont comparés, et la différence entre les longueurs des deux chaînes est retournée // Si les deux chaînes sont les mêmes, la différence entre les longueurs est de 0, c'est-à-dire que la même chaîne renvoie 0 retour Len1 - Len2; } La méthode ComparetoignoreCase (String STR) est implémentée de manière similaire. Le casse supérieur et inférieur des caractères est ignoré lors de la comparaison, et la méthode de mise en œuvre est la suivante:
public int compare (String S1, String S2) {int n1 = s1.length (); int n2 = s2.length (); int min = math.min (n1, n2); pour (int i = 0; i <min; i ++) {char c1 = s1.charat (i); char C2 = S2.Carat (i); if (c1! = c2) {c1 = caractères.touppercase (c1); c2 = caractères.touppercase (c2); if (c1! = c2) {c1 = caractères.tolowercase (c1); c2 = caractères.tolowercase (C2); if (c1! = c2) {// Pas de débordement à cause de la promotion numérique Retour C1 - C2; }}}} return n1 - n2; }String native Intern ()
Lorsque la méthode interne est appelée, si le pool contient déjà une chaîne égale à cet objet de chaîne (déterminé avec la méthode equals (objet)), la chaîne dans le pool est renvoyée. Sinon, ajoutez cet objet String au pool et renvoyez une référence à cet objet String.
Toutes les chaînes littérales et les expressions constantes d'attribution de chaîne sont exploitées à l'aide de la méthode interne, par exemple: chaîne str1 = "123";
Emplacement de la mémoire de la chaîne: piscine constante ou tas
Les objets de chaîne peuvent être créés directement via des littéraux ou via des constructeurs. Quelle est la différence?
1. Les objets de chaîne créés par des chaînes littérales ou littérales à travers des épissements "+" sont stockés dans le pool constant. Si le pool constant existe pendant la création réelle, la référence sera directement retournée. S'il n'existe pas, l'objet String sera créé.
2. Créez un objet de chaîne à l'aide du constructeur et créez un objet de chaîne directement dans le tas
3. Appelez la méthode des internes et renvoyer l'objet sera placé dans le pool constant (s'il n'existe pas, il sera placé dans le pool constant, et s'il existe, il sera renvoyé à la référence)
Ce qui suit est un exemple de l'allocation de mémoire des objets de chaîne:
String str1 = new String ("123"); String str2 = "123"; String str3 = "123"; String str4 = str1.intern (); System.out.println (str1 == str2); // FAUX STR1 crée un objet dans le tas, Str2 crée un objet dans le System de pool constant.out.println (str2 == str3); // true str2 crée un objet dans le pool constant, STR3 renvoie directement une référence à l'objet créé par STR2, donc STR2 et STR3 pointent vers le même objet dans le Pool System.out.out.out.print (str4 == STR3); // Vrai STR4 renvoie un objet avec une valeur de "123" dans la piscine constante, donc STR4, STR2 et STR3 sont égaux.À propos de l'exemple de couture de la chaîne:
classe publique StringTest {public statique final statique x = "ABC"; // constant x @test public void test () {String str5 = new String ("ABC"); String str6 = str5 + "def"; // Créer une chaîne str7 = "abc" + "def"; // String de pool constant str8 = x + "def"; // x est une constante, et la valeur est fixe, donc la valeur de x + "def" a été définie sur ABCDEF. En fait, après compilation, le code est équivalent à String str8 = "ABCDEF" String str9 = "ABC"; String str10 = str9 + "def"; //System.out.println(str6==Str7); // false System.out.println (str8 == str7); // true System.out.println (str10 == str7); // false System.out.println (x == str9); //vrai} }Le code décompilé sera clair en un coup d'œil:
L'allocation de la mémoire est la suivante:
String, StringBuffer, StringBuilder
Puisque la valeur de propriété [] tableau de caractères pour le stockage des chaînes maintenues en interne par type de chaîne est modifiée avec final:
/ ** La valeur est utilisée pour le stockage des caractères. * / Valeur de char finale privée [];
Il indique qu'il peut être modifié après l'attribution. Par conséquent, nous pensons que l'objet String est immuable une fois créé. Si vous rencontrez des opérations de chaîne d'épissage fréquentes pendant le développement, si vous utilisez le contact fourni par String ou utilisez directement la chaîne d'épissage "+", de nouvelles chaînes seront fréquemment générées, ce qui sera inefficace. Java fournit deux autres classes: StringBuffer et StringBuilder, qui sont utilisées pour résoudre ce problème:
Jetez un œil au code suivant:
String str1 = "123"; String str2 = "456"; String str3 = "789"; String str4 = "123" + "456" + "789"; // Ajouter des constantes, le compilateur reconnaît automatiquement la chaîne str4 = "123456789" String str5 = str1 + str2 + str3; // Variables de chaîne d'étape, il est recommandé d'utiliser StringBuilder StringBuilder SB = new StringBuilder (); SB.APPEND (STR1); SB.APPEND (STR2); SB.APPEND (STR3);
Ce qui suit est la mise en œuvre de la classe StringBuilder, qui intercepte uniquement une partie du code analysé:
La classe finale publique StringBuilder étend AbstractStringBuilder implémente Java.io.Serializable, CharSequence {// Split String @Override public StringBuilder append (String Str) {// Appeler la classe parent AbstractStringBuilder.APPEND Super.APPEND (STR); retourner ceci; }} Résumé classe AbstractStringBuilder implémente appendable, CharSequence {/ ** * Le tableau de caractères qui stocke les chaînes, type non finale, différent de la classe de chaîne * / char [] valeur; / ** * Le nombre est le nombre de caractères utilisés. * / int count; public abstractStringBuilder append (String str) {if (str == null) return appendNull (); int len = str.length (); // Vérifiez si la capacité doit être étendue pour assurer la mise en place de la manière dont le nombre + Len); // Copiez la chaîne STR pour valeur str.getchars (0, len, valeur, count); Count + = len; Renvoie ce;} private void assurecapacityInternal (int minimumcapacity) {// Code de trop-flux // minimumcapacity = count + str.length // si la capacité après Str est épissée est supérieure à la capacité de valeur, expanssez si (minimumcapacity - value.length> 0) {// Développement la capacité de référence et copie la valeur actuelle de la valeur de la valeur de la valeur à la valeur à l'étendue de la valeur de caractéristique, retour de la valeur de la valeur = la valeur de la valeur de la valeur = Arrays.CopyOf (valeur, newCapacity (minimumcapacity)); }} // StringBuilder Expansion Private int newcapacity (int mincapacity) {// Code de débordement // Calcule Capacité d'expansion // La longueur du tableau d'extension par défaut est étendue de 2 fois la longueur du groupe numéro (Valeur []), puis 2 sont ajoutées à la règle. Pourquoi ajouter 2? int newCapacity = (value.length << 1) + 2; if (newCapacity - mincapacity <0) {newCapacity = mincapacity; } return (newCapacity <= 0 || max_array_size - newcapacity <0)? HugeCapacity (mincapacité): nouvellecapacité; }}Il en va de même pour StringBuffer et StringBuilder. Le tableau de caractères de valeur [] maintenu en interne est mutable. La seule différence est que StringBuffer est thread-safe. Il synchronise toutes les méthodes. StringBuilder est sans filetage. Par conséquent, lorsque le fonctionnement multi-thread et le partage des variables de chaîne, StringBuffer est préféré pour le traitement d'épissage de chaîne. Sinon, StringBuilder peut être utilisé. Après tout, la synchronisation des threads apportera également une certaine consommation.
Résumer
Ce qui précède est l'intégralité du contenu de cet article. J'espère que le contenu de cet article a une certaine valeur de référence pour l'étude ou le travail de chacun. Si vous avez des questions, vous pouvez laisser un message pour communiquer. Merci pour votre soutien à wulin.com.