Die String-Klasse verwaltet intern einen Wert vom Typ char[], um Strings zu speichern. Der Quellcode ist relativ einfach.
Die Unveränderlichkeit von String spiegelt sich hauptsächlich in drei Aspekten wider:
Die String-Klasse ist als endgültiger Typ definiert . Kann nicht vererbt werden
Der Wert[] in String ist als endgültig definiert
Alle Operationen in String, die einen neuen String generieren, werden am aufgerufen unten Array.copy oder System.copy zum Generieren eines neuen String-Objekts
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; }
Bei den beiden oben genannten handelt es sich um einen speziellen Konstruktortyp. Der erste verwendet einen vorgefertigten String, um ein neues String-Objekt zu initialisieren. Die Konstruktormethode verweist direkt auf den Wert des neuen String-Objekts. Da String unveränderlich ist, muss das Wertobjekt hier nicht erneut kopiert werden. Der zweite Konstruktor scheint die Unveränderlichkeit des String-Typs zu zerstören (String ändert sich auch, wenn sich der Parameterwert ändert), aber dieser Konstruktor ist nicht als öffentlich deklariert und darf nur innerhalb des als öffentlich deklarierten Pakets String() verwendet werden char value[]) Die unterste Ebene ruft Array.copy auf, um die zugrunde liegende Datenkopie zu realisieren. Die Verwendung der beiden oben genannten Konstruktoren wird nicht mehr empfohlen.
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); }
Der obige Konstruktor ist typischer, und es gibt sie Viele andere Konstruktoren ähneln diesem oder dem zugrunde liegenden Konstruktor. Die Eingabeparameter sind ein char-Array (Byte[]), eine Offset-Offset-Position und ein Count-Offset. Die unterste Ebene ruft die Funktion Arrays.copy auf, um ein tiefes Kopieren durchzuführen.
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()); }
Die Eingabeparameter der beiden oben genannten Konstruktoren sind StringBuffer bzw. StringBuilder. Der einzige Unterschied besteht darin, dass StringBuffer threadsicher ist und das synchronisierte Schlüsselwort verwendet werden muss alle Anrufe.
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 und lastIndexOf sind hauptsächlich die zugrunde liegenden Aufrufe der Funktionen index und lastIndex. Sie werden feststellen, dass die zugrunde liegende Implementierung keine hat Besonders toll ist der KMP-Algorithmus, bei dem immer noch ein zeichenweises Scannen implementiert ist. Unter diesen verwendet lastIndexOf immer noch 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 wird verwendet, um ein Zeichen im String-Objekt durch ein anderes Zeichen zu ersetzen. Wenn das angegebene Zeichen nicht gefunden wird, wird es selbst zurückgegeben. Wenn es gefunden wird, wird ein neues String-Objekt erstellt gib es zurück.
---Ende des Wiederherstellungsinhalts---
Das obige ist der detaillierte Inhalt vonBeispielinterpretation des String-Quellcodes. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!