Home  >  Article  >  Java  >  Java—Principles and differences between StringBuffer and StringBuilder

Java—Principles and differences between StringBuffer and StringBuilder

高洛峰
高洛峰Original
2017-01-22 09:44:312002browse

I was looking for a job recently, and the examiner asked me a simple question: "What are the differences between StringBuffer and StringBuilder, and what are their application scenarios?" The editor's answer is shared with everyone below, so that everyone can learn in the future, and also be a good example Record.

In fact, just search Google and 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. , and StringBuilder does not have this modification and can be considered thread-unsafe.

In order to better understand the above answers, it is more practical to directly look at the source code implementation of StringBuffer and StringBuilder. As a programmer, "when in doubt, look at the source code" is the right way. I can say responsibly, Of course it has to be conditional!

In the implementation of jdk, both StringBuffer and StringBuilder inherit from AbstractStringBuilder. You can roughly understand the safety and non-safety of multi-threading by seeing the bunch of synchronized in front of the methods in StringBuffer.

Here is a casual 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 + is used directly for string connection, jvm will create multiple String objects. This results in a certain amount of overhead. AbstractStringBuilder uses a char array to save the string that needs to be appended. The char array has an initial size. When the length of the appended string exceeds the current char array capacity, the char array is dynamically expanded, that is, a larger period is reapplied. memory space, and then copies the current char array to a new location. Because the overhead of reallocating memory and copying is relatively high, every time you re-apply for memory space, you must apply for a memory space larger than the current need. Here it is 2 times.

Next, let’s have some fun!

Some information came out in Google:

[
StringBuffer started from JDK 1.0
StringBuilder started from JDK 1.5

From JDK 1.5 Initially, the connection operation (+) with string variables is implemented internally by the JVM using
StringBuilder, whereas previously this operation was implemented using StringBuffer.

Let’s look at its execution process through a simple program:

List 1 Buffer.java

public class Buffer {
public static void main(String[] args) {
String s1 = "aaaaa";
String s2 = "bbbbb";
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:

Java—Principles and differences between StringBuffer and StringBuilder

List 2 Buffer class bytecode

Combine List 1 and List 2 Correspondingly, 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 stores "aaaaa" into variable 1, and the latter is the same, sipush loads a short integer The constant value (-32768~32767) is pushed to the top of the stack, here is the constant "3694". For more Java instruction sets, please see another article "Java Instruction Set".

Let us directly see that 13, 13~17 new a StringBuffer object and call its initialization method, 20~21 first push variable 1 to the top of the stack through aload_1, as mentioned before, variable 1 is put is the string constant "aaaaa", and then calls the append method of StringBuffer through the instruction invokevirtual to splice "aaaaa" together, and the same goes for the subsequent 24 to 30 seconds. Finally, at 33, the toString function of StringBuffer is called to obtain the String result and stored in variable 3 through astore.

Some people may say after seeing this, "Since the JVM uses StringBuffer internally to connect strings, we don't need to use StringBuffer ourselves, just use "+"!". Is it? Of course not. As the saying goes, "There is a reason for existence." Let us continue to look at the bytecode corresponding to the subsequent loop.

37~42 are all preparations before entering the for loop. 37 and 38 are to set j to 1. 44 Here, j is compared with 10 through if_icmpge. If j is greater than 10, jump directly to 73, that is, the return statement exits the function; otherwise, it enters the loop, which is the bytecode of 47~66. Here we only need to look at 47 to 51 to know why we have to use StringBuffer to handle the string connection in the code, because every time the "+" operation is performed, the jvm has to create a new StringBuffer object to handle the string connection. This can be expensive when many string concatenation operations are involved.

For more Java-StringBuffer and StringBuilder principles and differences related articles, please pay attention to the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn