Recently, when I was looking for a job, the examiner asked me a simple question: "The difference between StringBuffer and StringBuilder, what are their application scenarios?" The editor's answer is shared with you below, so that it can be convenient for everyone to learn in the future, so as to make a record.
In fact, just look for the Google master and you will have the answer: StringBuffer is completely equivalent to the methods and functions in StringBuilder, but most of the methods in StringBuffer use the synchronized keyword for modification, so they are thread-safe. Without this modification, StringBuilder can be considered thread-unsafe.
In order to better understand the above answer, it is better to directly see that the source code implementation of StringBuffer and StringBuilder is more realistic. As a programmer, "If you have any questions, look at the source code" is the right way. I can say responsibly, of course, you have to have conditions!
In jdk's implementation, both StringBuffer and StringBuilder are inherited from AbstractStringBuilder. For the security and non-safety of multi-threading, you will have a rough understanding of the synchronized methods in StringBuffer.
Here I will briefly 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 use + directly for string connection, jvm will create multiple String objects, which will cause certain overhead. AbstractStringBuilder uses a char array to save the string that needs to be append. The char array has an initial size. When the string length of the append string exceeds the current char array capacity, the char array is dynamically expanded, that is, reapplying a larger memory space, and then copying the current char array to a new location. Because the overhead of re-allocating memory and copying is relatively large, each time you reapplying for the memory space is in the way that the memory space is larger than the current required, which is 2 times.
Next, have some fun!
Here are some information in Google:
【
StringBuffer started with JDK 1.0
StringBuilder started with JDK 1.5
Starting from JDK 1.5, the connection operation (+) with string variables is used internally by JVM
StringBuilder is implemented, and this operation was implemented using StringBuffer.
】
We look at the execution process through a simple program:
Listing 1 Buffer.java
public class Buffer { public static void main(String[] args) { String s1 = "aaaaa"; String s2 = "bbbbbb"; String r = null; int i = 3694; r = s1 + i + s2; for(int j=0;i<10;j++){ r+="23124"; } } }Use the command javap -c Buffer to view its bytecode implementation:
Listing 2 Buffer class bytecode
Corresponding List 1 and List 2, the ldc instruction in List 2 loads the "aaaa" string from the constant pool to the top of the stack, and istore_1 stores "aaaaa" in variable 1. The following is the same. 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 check another article "Java instruction set".
Let us directly see that 13, 13~17 is new to a StringBuffer object and call its initialization method. 20~21 is to first press variable 1 to the top of the stack through aload_1. As mentioned earlier, variable 1 is put into the string constant "aaaaa", and then call the append method of StringBuffer through the instruction invokevirtual to splice "aaaaa" together. The following 24~30 is the same. Finally, in 33, the toString function of StringBuffer is called to obtain the String result and stored in variable 3 through the store.
When we see this, someone may say, "Since the JVM uses StringBuffer to connect strings, we don't need to use StringBuffer ourselves, just use "+" just!" Is that true? Of course not. As the saying goes, "There is a reason for existence", let's continue to look at the bytecode corresponding to the subsequent loop.
37~42 are all some preparations before entering the for loop. 37, 38 set j to 1. 44 Here, if_icmpge compares j with 10. If j is greater than 10, it will jump directly to 73, that is, the return statement exits the function; otherwise, it enters the loop, that is, the bytecode of 47~66. Here we only need to look at 47 to 51 to know why we use StringBuffer in our code to handle string connections, because every time we perform the "+" operation, jvm has to new StringBuffer object to handle string connections, which will be very expensive when many string connection operations are involved.