May 31, 2021 Article blog
The article comes from the public number: Program New Horizons Author: Ugly Fat Man Ii Brother
Interview questions about strings, in addition to memory distribution
equals
are most commonly distinguished from
StringBuffer
and
StringBuilder
If you answer:
String
classes are immutable,
StringBuffer
and
StringBuilder
are variable classes,
StringBuffer
is thread-safe,
StringBuilder
is not thread-safe.
As far as the above summary is concerned, there seems to be a little less to know. This article takes you through a comprehensive look at the differences between the three of them and the underlying implementations.
As detailed in previous articles on
String
strings, its immutability is also caused by the generation of new strings in memory whenever a "plus" operation is passed.
String a = "hello ";
String b = "world!";
String ab = a + b;
For the above code, the memory distribution is as follows:
Where a and b are initialized in the string constant pool, the ab-stitched objects are in the heap. I
t's intuitive to see that after stitching up the new generation
String
a String object.
If you stitch multiple times, more than one intermediate object is generated.
The above conclusion was established prior to
Java8
when JDK optimized the stitching of the "plus" number, and the stitching described above was optimized for processing by
Java8
StringBuilder
append
methods.
stack=2, locals=4, args_size=1
0: ldc #2 // String hello
2: astore_1
3: ldc #3 // String world!
5: astore_2
6: new #4 // class java/lang/StringBuilder
9: dup
10: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
13: aload_1
14: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: aload_2
18: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
24: astore_3
25: return
Above, the result of the bytecode is decompiled by
the java
p -verbose
command, and it is clear that the creation of
StringBuilder
and the call to the 'append method' can be seen.
At this point, it would be wrong to add a general answer that multiple
String
objects are created by stitching strings with plus signs, so performance is worse than
StringBuilder
Because essentially the effect of plus-size stitching is eventually processed by the compiler and is consistent with
StringBuilder
If you use the following in your code:
StringBuilder sb = new StringBuilder("hello ");
sb.append("world!");
System.out.println(sb.toString());
The compiler's plug-in even suggests using
String
instead.
The core code implemented by
StringBuffer
and
StringBuilder
is basically the same, and much of the code is common.
Both classes are inherited from the abstract class
AbstractStringBuilder
Let's look at the differences from the construction method to the
append
method.
Let's start with
StringBuilder
construction method:
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
The
super
method is the construction method of the
AbstractStringBuilder
The same is true for implementations in the construction methods corresponding to
StringBuffer
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
StringBuffer
and
StringBuilder
are the same in terms of construction methods.
Here's a look at
append
method,
StringBuilder
implementation is as follows:
@Override
public StringBuilder append(String str) {
super.append(str);
return this;
}
StringBuffer
approach is as follows:
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
Obviously, the only difference in
StringBuffer
append
method implementation, except that the
toStringCache
variable is internally assigned
null
is that it is synchronized with
synchronized
toStringCache
is a string that is used to cache the last time the
toString
method is called, and the value changes when
StringBuffer
content changes.
By comparing the
append
method above, we can easily find that
StringBuffer
is thread-safe and
StringBuilder
is non-thread-safe.
Of course, using
synchronized
synchronization can reduce performance a lot.
StringBuffer
and
StringBuilder
call the construction method of the parent class:
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
With this construction method we can see that the key property they use to process string information is
value
At initialization, an array of
char[]
or
value
values, with a length of the incoming string length of plus 16 is initialized to store the actual string.
After calling the parent class construct method, the respective end methods are called (see the previous code), and the core processing in it calls the parent class's append method:
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
In the above code, the
str.getChars
method is used to stitch incoming
str
strings and fill them after the original
value
array.
count
is used to record the length already used in the current
value
number.
So, where does thread insecurity occur when synchronization operations are not
synchronized
T
he
count+=len
in the code above is not an atomic operation. F
or example,
count
current count is 5, both threads perform the operation at the same time, get a value of 5, assign a value to
count
after the addition, and both threads are assigned 6 instead of 7.
At this point, there is a thread insecurity.
Designing
String
as immutable in
Java
is the result of a combination of factors for the following reasons:
1, string constant pool needs, if the string is variable, change one object will affect another independent object. Unchanged This is also a prerequisite for the existence of a string constant pool.
2. Hash codes for objects in
Java
String
are frequently used, such as in containers such as HashMap.
The string unchanged guarantees the uniqueness of the hash code and can be cached and used in the direction.
3, security, to ensure that
String
when the parameters are passed to stay the same, to avoid security risks.
For example, in the database user name, password, access path and other transmission process remains unchanged, to prevent changing the string pointing to the value of the object is changed.
4, because the string variable is immutable, in multithreaded can be shared for use.
Simply rote interview questions we will all, but in the process of remembering the interview questions to learn more about the underlying implementation principles, not only to help understand "why", but also to learn more relevant knowledge and principles.
In this article, you've simplified the steps of copying, array expansion, and so on for
StringBuilder
and
StringBuffer
internal data, so interested friends can continue to delve back into the source code.
Here's
W3Cschool编程狮
about
the Java interview question: Talk about the differences between Stringing, StringBuffer, StringBuilder?
Related to the introduction, I hope to help you.