1. Einführung in String, Common Method Quellcode Analyse
2. Analyse konstanter Pool -Pool -Pool
Gemeinsame Methoden
gleich
trimmen
ersetzen
concat
Teilt
Starten und Ende
Substring
touppercase () und tolowerCase ()
Vergleich
Einführung in String
Die String -Klasse wird durch endgültig geändert, was bedeutet, dass das String -Objekt unveränderlich ist und gleichzeitige Programme Immutables bevorzugen. Die String -Klasse implementiert die serialisierbaren, vergleichbaren und charsequence -Schnittstellen.
Beginnen Sie mit einem Stück Code:
public void StringTest () {String a = "a"+"b" +1; Zeichenfolge b = "ab1"; System.out.println (a == b);}Ratet mal, was das Ergebnis ist? Wenn Ihre Schlussfolgerung wahr ist. OK, lass uns einen weiteren Code haben:
public void StringTest () {String a = new String ("ab1"); Zeichenfolge b = "ab1"; System.out.println (a == b);}Was ist das Ergebnis? Die richtige Antwort ist falsch.
Mal sehen, wie der vom Compiler kompilierte Code kompiliert wurde
// Der erste Code public void stringstest () {String a = "ab1"; Zeichenfolge b = "ab1"; System.out.println (a == b);} // Der zweite Code public void stringstest () {String a1 = new String ("ab1"); Zeichenfolge b = "ab1"; System.out.println (a1 == b);}Mit anderen Worten, das erste Code -Stück wurde während der Kompilierungsperiode optimiert, da der Compiler feststellte, dass die Auswirkungen von "A"+"B" +1 und "AB1" gleich sind und beide aus Immutables bestehen. Aber warum befasst sich ihr Speicher gleich? Wenn Sie sich immer noch daran interessieren, schauen wir uns einige wichtige Quellcodes der String -Klasse an.
Quellcode
1. String -Attribute
Die String -Klasse enthält ein unveränderliches Zeichen -Array zum Speichern von Zeichenfolgen, und ein INT -Variable -Hash wird verwendet, um den berechneten Hash -Wert zu speichern.
/** Der Wert wird für den Zeichenspeicher verwendet. */private endgültige Zeichen [];/** Cache den Hash -Code für die Zeichenfolge*/private int Hash; // standardmäßig 0/** serialVersionuid von JDK 1.0.2 für Interoperabilität verwenden*/privates statisches Final Long Serialversionuid = -6849794470754667710L;
2. Stringkonstruktor
// Konstruktoren ohne Parameter sind im Allgemeinen nutzlos, da Wert ein unveränderlicher public string () {this.Value = new char [0];} // Der Parameter ist der String Typ public String (String Original) {this.value = original.Value; this.hash = original.hash;}//The parameter is a char array, use the Arrays class in the java.utils package to copy public String(char value[]) { this.value = Arrays.copyOf(value, value.length);}// Start from the offset position in the bytes array, encode the bytes of length in the charsetName format and copy it to valuepublic String(byte Bytes [], int -offset, int länge, String charSetName) löst nicht unterstütztenCodingException {if (charSetName == null) aus, die neue nullPointerexception ("charSetName") werfen; CheckBounds (Bytes, Offset, Länge); this.value = StringCoding.decode(charsetName, bytes, offset, length);}//Call the public String(byte bytes[], int offset, int length, String charsetName) constructor public String(byte bytes[], String charsetName) throws UnsupportedEncodingException { this(bytes, 0, bytes.length, charsetName);}3.. Gemeinsame Methoden der String
1. gleich
boolean Equals (Object Anobject) öffentliches boolean gleich (Object AnObject) {// Wenn die Referenz dasselbe Objekt ist, geben Sie true zurück, wenn (this == anObject) {return true; } // Wenn Daten vom Typ String keine Zeichenfolge sind, geben Sie false zurück, wenn (AnObject Instance von String) {String anotherString = (String) AnObject; int n = value.length; // Wenn die Länge des Zeichenarrays nicht gleich ist, geben Sie false zurück, wenn (n == AnotherString.Value.length) {char v1 [] = Wert; char v2 [] = anotherstring.Value; int i = 0; // urteilen Sie nach der Vorderseite vom einzelnen Charakter, wenn es Ungleichheit gibt, geben Sie falsche, während (n--! = 0) {if (v1 [i]! = V2 [i]) Return false; i ++; } // Jedes Zeichen ist gleich, return true return true; }} return false;}Zeichenfolge e1 = "good"; String e2 = "Gut jeden Tag"; e1.equals (e2); // false zurückgeben
1 Bestimmen Sie zunächst, ob das gleiche Objekt referenziert wird. ==, dh fest, ob die Speicheradressen der beiden Referenzen gleich sind. Wenn dieselbe, wird es direkt wahr zurückgegeben.
2 bestimmt, ob die Typen gleich sind und ob sie gleich Datentyp sind
3 Wenn der gleiche Typ verwendet wird, ist die Länge des konvertierten Zeichenarrays gleich.
4 Vergleichen Sie, ob jedes Zeichen von hinten nach vorne gleich ist
Urteilsverordnung =》 1. Speicheradresse 2. Datentyp 3. Zeichenarraylänge 4. Einzelzeichenvergleich
2. Vergleich
int vergleicheto (String anotherString) public int vergleicheto (String anotherString) {// Die Länge der Zeichenfolge des eigenen Objekts len1 int len1 = value.length; // Die Länge der Schnur des verglichenen Objekts len2 = anTherstring.Value.Length; // Der Mindestwert der Länge von zwei Zeichenfolgen lim int lim = math.min (len1, len2); char v1 [] = Wert; char v2 [] = anotherstring.Value; int k = 0; // Aus dem ersten Zeichen des Wertes bis zur Mindestlänge LIM, wenn die Zeichen nicht gleich sind, geben Sie sich selbst zurück (Zeichen, in denen die Objekte nicht gleich sind - die Zeichen, die verglichen werden), während (k <lim) {char c1 = v1 [k]; char c2 = v2 [k]; if (c1! = c2) {return c1 - c2; } K ++; } // Wenn die Fronten alle gleich sind, return (sich selbst Länge - Länge des Objekts verglichen).String co1 = "Hallo"; String co2 = "Hallo"; String co3 = "Hallo"; System.out.println (co1.comPareto (CO2)); // 0System.out.println (co1.comPareto (CO3)); // -4
Diese Methode ist genial geschrieben, und Sie können die Charaktergröße zuerst von 0 beurteilen.
Wenn der Vergleich zwischen den beiden Objekten die Zeichen vergleichen kann, ist die Länge des verglichenen Objekts direkt zurückgegeben. Wenn die Länge der beiden Saiten gleich ist, beträgt die Rendite 0, was die drei Situationen geschickt beurteilt.
3.HashCode
int HashCode () public int HashCode () {int H = Hash; // Wenn der Hash nicht berechnet wurde und die Zeichenfolge nicht leer ist, wird die Hashcode -Berechnung durchgeführt, wenn (h == 0 && value.length> 0) {val [] = value; // Berechnungsprozess // s [0]*31^(n-1) + s [1]*31^(n-2) + ... + s [n-1] für (int i = 0; i <value.length; i ++) {H = 31*H + val [i]; } // Hash -Zuordnung Hash = H; } return h;}Zeichenfolge a = "toyou"; char val [] = a.therararray (); char c1 = 't'; char c2 = 'a'; int f = c1; int e = c2; System.out.println (e); // 97 asystem.out.println (f); // 116 TSystem.out.println (31*val [0]); // 3596System.out.println (31*C1); // 3596 // HashCode -Berechnung, da Zeichenzeichen automatisch in die entsprechende Int -Form konvertiert werden können
Die String -Klasse überschreibt die HashCode -Methode, und die HashCode -Methode im Objekt ist ein nativer Aufruf.
Der Hash der String -Klasse wird unter Verwendung von Polynomen berechnet. Wir können den gleichen Hash durch verschiedene Zeichenfolgen vollständig erhalten. Daher ist der Hashcode von zwei String -Objekten gleich, was nicht bedeutet, dass die beiden Zeichenfolgen gleich sind.
Der HashCode desselben String -Objekts muss gleich sein, aber der HashCode ist derselbe, nicht unbedingt dasselbe Objekt
4.Startswith
boolean startswith (String prefix, int toffset) public boolean startswith (String prefix, int toffset) {char ta [] = value; int to = toffset; char pa [] = Präfix.Value; int po = 0; int pc = Präfix.Value.length; // Hinweis: Toffset könnte in der Nähe von -1 >>> 1 liegen. // Wenn die Startadresse weniger als 0 oder (Startadresse + Länge des verglichenen Objekts) ist, ist größer als die Länge des eigenen Objekts, geben Sie False zurück, wenn ((toffset <0) || (toffset> value.length - pc)) {return false; } // Vergleiche vom Ende des Objekts, das verglichen wird (--pc> = 0) {if (ta [to ++]! = Pa [po ++]) {return false; }} return true;} public boolean startsWith (String prefix) {return startsWith (Präfix, 0);} public boolean endswith (String -Suffix) {return startsWith (Suffix, Value.Length - Suffix.Value.Length);} String d = "www.58fxp.com"; System.out.println (D.Startswith ("www"); // true system.out.println (d.endswith ("com")); // WAHRStart- und Endvergleich sind gemeinsame Methoden. Wenn Sie beispielsweise beurteilen, ob sich eine Zeichenfolge aus dem HTTP -Protokoll stammt oder zunächst beurteilt, ob eine Datei eine MP3 -Datei ist, können Sie diese Methode zum Vergleich verwenden.
5.Concat
String concat (string str) public String concat (string str) {int otherLen = str.length (); // Wenn die hinzugefügte Zeichenfolge leer ist, geben Sie das Objekt selbst zurück, wenn (otherLen == 0) {return this; } int len = value.length; char buf [] = arrays.copyof (Wert, len + otherlen); Str.Getchars (buf, len); Neue String zurückgeben (BUF, TRUE);} String cat = "viel"; String newcat = cat.concat ("yes"); // viel jaDie CONCAT -Methode ist auch eine der häufig verwendeten Methoden. Es bestimmt zunächst, ob die hinzugefügte Zeichenfolge leer ist, um zu entscheiden, ob ein neues Objekt erstellt werden soll.
1 Wenn die gespleißte Zeichenlänge 0 beträgt, kehren Sie direkt zum ursprünglichen Zeichenobjekt zurück
2 Die gespleißten Zeichen sind nicht leer und geben ein neues Zeichenobjekt zurück
Bestimmen Sie die Zeichenlänge, um ein neues Objekt zu erzeugen
6. Replace
String ersetzen (char Oldchar, char Newchar) öffentliche Zeichenfolge Ersatz (Zeichen Oldchar, char NewChar) {// Vergleiche die alten und neuen Werte zuerst, wenn (oldChar! = NewChar) {int len = value.length; int i = -1; char [] val = Wert; / * Vermeiden Sie GetField Opcode */ // Die Position finden, in der der alte Wert zuerst erscheint, während (++ i <len) {if (val [i] == Oldchar) {break; }} // Ersetzen Sie aus dieser Position bis zum Ende den alten Wert, der mit dem neuen Wert erscheint, wenn (i <len) {char buf [] = new char [len]; für (int j = 0; j <i; j ++) {buf [j] = val [j]; } while (i <len) {char c = val [i]; buf [i] = (c == Oldchar)? Newchar: C; i ++; } return New String (buf, true); }} return this;} String R1 = "Wie geht es dir"; String R2 = R1.Replace ("Do", "IS"); System.out.println (R2); // Wie geht es dir?Diese Methode hat auch eine gewisse Klugheit, z. B. herauszufinden, wo der alte Wert zu Beginn erscheint, was eine Vergleichszeit spart.
Die Methode Ersatz (String Oldstr, String NewStr) wird nach regulären Ausdrücken beurteilt.
7.TRIM
String trim () public String trim () {int len = value.length; int st = 0; char [] val = Wert; / * Getfield Opcode vermeiden */ // Die Position ohne Leerzeichen vor der Zeichenfolge finden ((st <len) && (val [st] <= '')) {st ++; } // Die Position ohne Leerzeichen am Ende der Zeichenfolge finden ((st <len) && (val [len-1] <= '') {len--; } //, wenn vor und danach keine Leerzeichen vorhanden sind, geben Sie die Zeichenfolge selbst zurück ((st> 0) || (len <value.length))? Substring (ST, Len): Dies;} String t1 = "Public void"; // Ein Speicherplatz vor und nach System.out.println ("T1:"+t1.length ()); // 13 mit Speicherlänge String t2 = t1.trim (); System.out.println ("T2:"+t2.Length ()); // 11 Entfernen Sie das Space System.out.println (T2);8.Intern
String personal () public native String praktikum ();
String dd = new String ("bb"). Praktion ();Die Ntern -Methode ist ein nationaler Aufruf, und ihre Funktion besteht darin, Objekte mit gleichem Wert durch die Equals -Methode im konstanten Pool im Methodenbereich zu finden.
Wenn Sie nicht gefunden werden, öffnen Sie einen Platz im konstanten Pool, um die Zeichenfolge zu speichern, und geben Sie den Verweis auf die entsprechende Zeichenfolge zurück. Andernfalls geben Sie den Verweis auf das String -Objekt direkt zurück im konstanten Pool.
Sie können auch das für die neue Methode erstellte Zeichenobjekt erzwingen, um festzustellen, ob der konstante Pool bereits vorhanden ist.
Geben Sie den zweiten Code in die Einführung ein
// String a = new String ("ab1"); // wechseln Sie in String a = new String ("ab1"). Praktion ();Das Ergebnis ist wahr, da die von A angezeigte Adresse aus dem konstanten Pool stammt und die von B durch B gerichtete String -Konstante diese Methode standardmäßig nennt, sodass A und B beide auf denselben Adressraum verweisen.
int Hash32 () private transient int hash32 = 0; int Hash32 () {int H = Hash32; if (0 == H) {// Harmless Data Race auf Hash32 hier. H = sun.misc.hashing.murmur3_32 (Hashing_seed, Wert, 0, Wert.Length); // Stellen Sie sicher, dass das Ergebnis nicht Null ist, um eine Neukalkierung von H = (0! = H) zu vermeiden? H: 1; Hash32 = H; } return h;}Wenn in JDK1.7 die String-Klasse als Schlüssel verwendet wird, verwendet die Hash-bezogene Sammlungsklasse die HashCode-Methode nicht mehr zu diskreten Daten, sondern die Hash32-Methode.
Diese Methode verwendet die aktuelle Zeit des Systems, die Stringklassenadresse, die Systemklassenadresse usw. als Faktoren zur Berechnung des Hash -Saatguts. Durch den Hash-Samen wird ein 32-Bit-Int-Wert durch den Hash-Samen erhalten.
public int length () {return value.length;} public String toString () {return this;} public boolean isempty () {return value.length == 0;} public charat (int index) {if ((index <0) || (Index> = value.Length)) {Wurfneue neue stringIndexoutofBoundSexception (Index); } Rückgabewert [Index];}Die oben genannten sind einige einfache gemeinsame Methoden.
Zusammenfassen
String -Objekte sind unveränderliche Typen. String -Methoden mit Rückgabe -String -String -Rückgabe jedes Mal, wenn ein neues String -Objekt zurückgegeben wird, mit Ausnahme bestimmter Bedingungen einiger Methoden, um sich selbst zurückzugeben.
Drei Möglichkeiten zum Vergleich von String -Objekten:
== Speichervergleich: Vergleichen Sie direkt die Speicherwerte, auf die die beiden Referenzen genau, prägnant und unkompliziert sind.
Equals String Value -Vergleich: Vergleichen Sie, ob die wörtlichen Werte der beiden referenzierten Objekte gleich sind.
Vergleich der HashCode -String -Numerikalisierung: Numerikalisierung von Zeichenfolgen. Die beiden referenzierten Hashcodes sind gleich, und der Speicher ist nicht garantiert gleich, und die wörtlichen Werte sind nicht garantiert garantiert.
Designidee des String Constant Pools
1. ursprüngliche Absicht des String Constant Pool Designs
Jede Zeichenfolge ist ein String -Objekt, und Zeichenfolgen werden häufig in der Systementwicklung verwendet. Wenn er wie andere Objekte erstellt und zerstört wird, wird dies die Leistung des Programms stark beeinflussen.
Um die Leistung zu verbessern und den Speicheraufwand zu reduzieren, optimiert JVM beim Instanziieren von Saiten.
Für Zeichenfolgen wird ein String -konstanter Pool geöffnet, ähnlich einem Cache -Bereich
Stellen Sie beim Erstellen einer String -Konstante zunächst fest, ob der String Constant Pool existiert.
Die Zeichenfolge gibt eine referenzierte Instanz zurück, existiert nicht, instanziiert die Zeichenfolge und stellt sie in den Pool.
Die Grundlagen erkennen
Die Grundlage für die Implementierung dieser Optimierung besteht darin, dass jede String -Konstante eine endgültige modifizierte Konstante ist, sodass sich keine Sorgen um Datenkonflikte im konstanten Pool machen müssen.
Der von der Laufzeitinstanz erstellte Global String Constant Pool enthält eine Tabelle, in der immer eine Referenz für jedes einzigartige String -Objekt im Pool beibehalten wird, was bedeutet, dass sie sich immer auf Objekte im String Constant Pool beziehen, sodass diese Zeichenfolgen im konstanten Pool nicht vom Müllkollektor erfasst werden.
Haufen, Stapel, Methodenbereich
Verstehen von String Constant Pools und schauen Sie sich zunächst den Bereich der Stapelmethode an
Haufen
Was gespeichert wird, ist ein Objekt, jedes Objekt enthält eine entsprechende Klasse
Der JVM hat nur einen Haufen Bereich und wird von allen Threads geteilt. Es gibt keine grundlegenden Typen und Objektreferenzen im Haufen, sondern nur das Objekt selbst
Objekte werden vom Müllsammler gesammelt, sodass Größe und Lebenszyklus nicht bestimmt werden müssen
Stapel
Jeder Thread enthält einen Stapelbereich, der nur grundlegende Datentypobjekte und benutzerdefinierte Objektreferenzen speichert.
Die Daten (primitive Typ und Objektreferenz) in jedem Stapel sind privat
Der Stapel ist in drei Teile unterteilt: den grundlegenden variablen Bereich, den Kontext der Ausführungsumgebung und den Betriebsanweisungsbereich (Speichern von Betriebsanweisungen)
Die Datengröße und der Lebenszyklus sind sicher, und wenn keine Bezugnahme auf diese Daten zeigt, verschwinden die Daten.
Methodenbereich
Statische Zonen werden wie Haufen von allen Threads geteilt
Der Methodenbereich enthält Elemente, die im gesamten Programm immer einzigartig sind, wie z. B. Klassen- und statische Variablen.
String Constant Pool
String Constant Pool existiert im Methodenbereich
Code: Stack Method Area speichert Zeichenfolgen
String str1 = "abc"; String str2 = "abc"; String str3 = "abc"; String str4 = new String ("abc"); String str5 = new String ("abc");Interviewfragen
String str4 = neuer String ("ABC") Wie viele Objekte werden erstellt?
Split: str4 =, new String (), "ABC"
Sie können ein neues Objekt über eine neue Methode erstellen. Die neue Methode erstellt ein sofortiges Objekt und geht nicht zum konstanten Pool, um festzustellen, ob es bereits existiert. Solange neu, wird ein neues Objekt instanziiert.
"ABC" Jede Zeichenfolge ist ein String -Objekt. Wenn es keinen ständigen Pool gibt, wird ein neues Objekt erstellt und in den konstanten Pool gesteckt. Andernfalls wird die Objektreferenz zurückgegeben.
Weisen Sie die Objektadresse Str4 zu und erstellen Sie eine Referenz
Wenn also im konstanten Pool kein "ABC" -Stuch vorhanden ist, erstellen Sie zwei Objekte, erstellen Sie sonst ein Objekt und erstellen Sie eine Referenz
String str1 = new String ("a"+"b"); Wie viele Objekte werden erstellt? String str2 = new String ("ABC") + "ABC"; Wie viele Objekte werden erstellt?
Die obige umfassende Analyse des Java -String -Quellcodes und des String Constant Pools ist der gesamte Inhalt, den ich mit Ihnen teile. Ich hoffe, Sie können Ihnen eine Referenz geben und ich hoffe, Sie können wulin.com mehr unterstützen.