Java — the principle and difference between StringBuffer and StringBuilder
Recently, when I was looking for a job, the examiner asked me a simple question: "what is the difference between StringBuffer and StringBuilder, and what are their application scenarios?", Here are some answers to share with you, so that you can learn from them in the future and make a record.
In fact, as long as you find the great God of Google, you will have the answer: the methods and functions in StringBuffer and StringBuilder are completely equivalent, but most of the methods in StringBuffer are modified with the synchronized keyword, so they are thread safe. Without this modification, StringBuilder can be considered thread unsafe.
In order to better understand the above answers, it is more realistic to directly look at the source code implementation of StringBuffer and StringBuilder. As a program ape, "if you have questions, look at the source code" is the right way. I can responsibly say that, of course, you have to be conditional!
In the implementation of JDK, both StringBuffer and StringBuilder inherit from abstractstringbuilder. For the safety and non safety of multithreading, you can see a bunch of synchronized methods in front of StringBuffer.
Let's talk about the implementation principle of abstractstringbuilder: we know that using StringBuffer is nothing more than to improve the efficiency of string connection in Java, because if you directly use + for string connection, the JVM will create multiple string objects, resulting in certain sales. Abstractstringbuilder uses a char array to save the string to append. The char array has an initial size. When the length of the append string exceeds the capacity of the current char array, the char array will be dynamically expanded, that is, re apply for a larger memory space, and then copy the current char array to a new location, Because the overhead of reallocating memory and copying is relatively large, each time you re apply for memory space, you apply for more than the current required memory space, which is twice here.
Next, play some fun!
Some information came out of Google:
[StringBuffer starts with JDK 1.0 and StringBuilder starts with JDK 1.5
Starting from JDK 1.5, the connection operation (+) with string variables is implemented by StringBuilder within the JVM, while the previous operation was implemented by StringBuffer.]
Let's look at the execution process through a simple program:
Listing 1 buffer java
Use the command javap - C buffer to view its bytecode implementation:
Listing 2 buffer class bytecode
Comparing Listing 1 with Listing 2, the LDC instruction in the bytecode in Listing 2 loads the "AAAAA" string from the constant pool to the top of the stack, iStore_ 1 save "AAAAA" to variable 1. As in the following, sipush pushes a short integer constant value (- 32768 ~ 32767) to the top of the stack. Here is the constant "3694". For more Java instruction sets, please see another article "Java instruction sets".
Let's directly see that 13,13 ~ 17 is a new StringBuffer object and call its initialization method, and 20 ~ 21 is through aload first_ 1 press variable 1 to the top of the stack. As mentioned earlier, variable 1 puts the string constant "AAAAA", and then call the append method of StringBuffer through the instruction invokevirtual to splice the "AAAAA". The same is true for the following 24 ~ 30. Finally, at 33, call the toString function of StringBuffer to obtain the string result and store it in variable 3 through astore.
Some people may say, "since StringBuffer is used to connect strings within the JVM, we don't need to use StringBuffer, just use" + "directly!" is it? Of course not. As the saying goes, "there is a reason for it", let's continue to look at the byte code corresponding to the following loop.
37 ~ 42 are some preparations before entering the for loop. 37 and 38 set J to 1. 44 here through if_ Icmpge compares J with 10. If J is greater than 10, it directly jumps to 73, that is, the return statement exits the function; Otherwise, it enters the loop, that is, 47 ~ 66 bytecode. Here, we only need to look at 47 to 51 to know why we need to use StringBuffer to handle string connection in the code, because each time the "+" operation is performed, the JVM needs to create a new StringBuffer object to handle string connection, which will be very expensive when many string connection operations are involved.