Maison >Java >javaDidacticiel >Exemple d'interprétation du code source de String
La classe String maintient en interne une valeur de type char[] pour stocker les chaînes. Le code source est relativement simple.
L'immuabilité de String se reflète principalement sous trois aspects :
La classe String est définie comme un type final. . Ne peut pas être hérité
La valeur[] dans String est définie comme finale
Toutes les opérations dans String qui génèrent une nouvelle String sont appelées à la fin. bottom Array.copy ou System.copy pour générer un nouvel objet String
public String(String original) { this.value = original.value; this.hash = original.hash; } String(char[] value, boolean share) { // assert share : "unshared not supported"; this.value = value; }Les deux ci-dessus sont un type spécial de constructeur. Le premier utilise une chaîne prête à l'emploi pour initialiser un nouvel objet String. La méthode constructeur pointe directement la valeur du nouvel objet String vers l'ancien objet valeur. Puisque String est immuable, il n’est pas nécessaire de recopier l’objet valeur ici. Le deuxième constructeur semble détruire l'immuabilité du type String (String changera également lorsque la valeur du paramètre change), mais ce constructeur n'est pas déclaré public et ne peut être utilisé que dans le package String() déclaré public. char value[]) La couche inférieure appelle Array.copy pour réaliser la copie des données sous-jacentes. Les deux constructeurs ci-dessus ne sont plus recommandés
public String(char value[], int offset, int count) { if (offset < 0) { throw new StringIndexOutOfBoundsException(offset); } if (count < 0) { throw new StringIndexOutOfBoundsException(count); } // Note: offset or count might be near -1>>>1. if (offset > value.length - count) { throw new StringIndexOutOfBoundsException(offset + count); } this.value = Arrays.copyOfRange(value, offset, offset+count); }Le constructeur ci-dessus est plus typique et il existe de nombreux autres constructeurs. .Ils sont similaires ou le constructeur sous-jacent est appelé. Les paramètres d'entrée sont un tableau de caractères (byte[]), une position de décalage et un décalage de nombre. La couche inférieure appelle la fonction Arrays.copy pour effectuer une copie approfondie.
public String(StringBuffer buffer) { synchronized(buffer) { //保证线程安全 this.value = Arrays.copyOf(buffer.getValue(), buffer.length()); } } public String(StringBuilder builder) { this.value = Arrays.copyOf(builder.getValue(), builder.length()); }Les paramètres d'entrée des deux constructeurs ci-dessus sont respectivement StringBuffer et StringBuilder. La couche inférieure appelle Arrays.copyOf. La seule différence est que StringBuffer est thread-safe et que le mot clé synchronisé doit être utilisé dans. tous les appels. 3. Autres méthodes
static int indexOf(char[] source, int sourceOffset, int sourceCount, char[] target, int targetOffset, int targetCount, int fromIndex) { if (fromIndex >= sourceCount) { return (targetCount == 0 ? sourceCount : -1); } if (fromIndex < 0) { fromIndex = 0; } if (targetCount == 0) { return fromIndex; } char first = target[targetOffset]; int max = sourceOffset + (sourceCount - targetCount); for (int i = sourceOffset + fromIndex; i <= max; i++) { /* Look for first character. */ if (source[i] != first) { while (++i <= max && source[i] != first); } /* Found first character, now look at the rest of v2 */ if (i <= max) { int j = i + 1; int end = j + targetCount - 1; for (int k = targetOffset + 1; j < end && source[j] == target[k]; j++, k++); if (j == end) { /* Found whole string. */ return i - sourceOffset; } } } return -1; } static int lastIndexOf(char[] source, int sourceOffset, int sourceCount, char[] target, int targetOffset, int targetCount, int fromIndex) { /* * Check arguments; return immediately where possible. For * consistency, don't check for null str. */ int rightIndex = sourceCount - targetCount; if (fromIndex < 0) { return -1; } if (fromIndex > rightIndex) { fromIndex = rightIndex; } /* Empty string always matches. */ if (targetCount == 0) { return fromIndex; } int strLastIndex = targetOffset + targetCount - 1; char strLastChar = target[strLastIndex]; int min = sourceOffset + targetCount - 1; int i = min + fromIndex; startSearchForLastChar: while (true) { while (i >= min && source[i] != strLastChar) { i--; } if (i < min) { return -1; } int j = i - 1; int start = j - (targetCount - 1); int k = strLastIndex - 1; while (j > start) { if (source[j--] != target[k--]) { i--; continue startSearchForLastChar; } } return start - sourceOffset + 1; } }indexOf et lastIndexOf sont principalement les appels sous-jacents des fonctions index et lastIndex En parcourant le code, vous constaterez que l'implémentation sous-jacente n'a pas de fonction. Algorithme kmp particulièrement génial, c'est toujours une analyse caractère par caractère qui est implémentée. Parmi eux, lastIndexOf utilise toujours continue startSearchForLastChar ;
public String replace(char oldChar, char newChar) { if (oldChar != newChar) { int len = value.length; int i = -1; char[] val = value; /* avoid getfield opcode */ while (++i < len) { if (val[i] == oldChar) { break; } } //如果找不到则返回this if (i < len) { char buf[] = new char[len]; for (int j = 0; j < i; j++) { buf[j] = val[j]; } while (i < len) { char c = val[i]; //替换 buf[i] = (c == oldChar) ? newChar : c; i++; } //返回新的String,利用上述包内的非public构造函数 return new String(buf, true); } } return this; }replace est utilisé pour remplacer un caractère dans l'objet String par un autre caractère. Si le caractère spécifié est introuvable, il retournera lui-même. S'il est trouvé, un nouvel objet String sera créé et. est revenu. ---Fin du contenu de récupération---
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!