Introduction
The String class and its associated StringBuilder, StringBuffer classes are used quite a lot in Java, and are also essential for interviews at various companies. So, this week, I'm going to take some time to read through the String, StringBuilder, and StringBuffer classes of related code.
Non-variability of string
This feature is a very important feature of String, for in-depth understanding, I directly paste its source code
public string concat (string str) {int otherlen = Str.length (); if (Otherlen = = 0) {return this; } int len = value.length; Char buf[] = arrays.copyof (value, Len + Otherlen); Str.getchars (buf, Len); return new String (buf, true); }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) {b Reak; }} 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++; } return new StrinG (buf, true); }} return this; }public String substring (int beginindex, int endIndex) {if (Beginindex < 0) {throw new Stringindexo Utofboundsexception (Beginindex); } if (EndIndex > Value.length) {throw new stringindexoutofboundsexception (EndIndex); } int sublen = Endindex-beginindex; if (Sublen < 0) {throw new stringindexoutofboundsexception (Sublen); } return ((Beginindex = = 0) && (endIndex = = value.length))? This:new String (value, Beginindex, Sublen); } .....
Through the code of the above methods, we can draw the following conclusions:
- The String object is immutable. The so-called immutable meaning is that we use many methods to modify the string, as shown in the following:
public static void main(String[] args) { String str = "test"; str = str + "a"; System.out.println(str);//testa str += "b"; System.out.println(str);//testab }
Methods such as the above + and concat, replace, and so on, appear to change the string value, ultimately creating a completely new string object that contains the modified string content. The object "Test", which Str points to first, stays in the original physical position. Each method operation is actually a copy of a reference, returned a new object, the above example of the original "test" is still in the original place.
Some myths: The immutability of String is not because of the following statement
private final char value[];
Final in a reference type, just make sure that you cannot point to other references, and you cannot ensure that the referenced changes are made. Value is private, although String does not provide a way to change the value, but it can be changed by reflection.
The + and + = symbols of string
It is well known that C + + can overload operators, but Java does not allow programmers to overload operators, while the + and + + symbols of string violate this rule. As we all know, the two operators in Java are concatenation of strings, look at the following code:
class Test{ public static void main(String[] args){ String str = "a"; str +="hello" + "world" + "!"; System.out.println(str);//ahelloworld! String pStr = "a" + str + "b"; System.out.println(pStr);//aahelloworld!b }}
If the character follows the immutability of a String that we understand, then when doing the + operation more than once, the intermediate files should be generated before the final result, so is that really the case? If you think about it, you know how much efficiency and performance are bad. We decompile the code.
javap -c Test
It produces the following JVM bytecode:
As we can see, in the above code, the compiler automatically introduces the Java.lang.StringBuilder class to us and uses the append (String str) method of this class, eventually using toString () to produce a string string and Assigned value.
Stitching strings in loops do not use string
So, can we happily use the + and + = two operators? No! What the compiler can do is also limited.
public class Test { public static void main(String[] args) { String s = ""; long start = System.currentTimeMillis(); for (int i = 0; i <100000 ; i++) { s += "a"; } long end = System.currentTimeMillis(); System.out.println("String time:"+ (end - start)); StringBuilder sb = new StringBuilder(""); long start2 = System.currentTimeMillis(); for (int i = 0; i <100000 ; i++) { sb.append("a"); } long end2 = System.currentTimeMillis(); System.out.println("StringBuilder time:"+ (end2 - start2)); }}
In the above code, the output is like this, and I also removed the time spent in intermediate load classes:
String time:2573StringBuilder time:5
Why is the gap so big?
Similarly, we decompile this file, and the first loop has the following byte code:
It can be seen that 10 to 40 is our loop body, in which there is a new operation, which means that each time a loop is made, a StringBuilder object is created, each time using the ToString () method. And these processes are quite influential in performance.
The second loop has the following byte code:
From the above we can see that the loop is from 95 to 113 rows, and in this process, there is always only one StringBuilder object, that is, it does not produce new objects, it is conceivable how the performance of the two between the difference.
Therefore, the concatenation string in the loop is not used in string, which may be encountered when writing the ToString () method.
OK, today we analyze here, next article farewell.
Also, reprint please indicate the source.
Parsing string, StringBuilder, StringBuffer classes in Java (i)