Understanding String, StringBuffer, StringBuilder Differences and Source Code Implementation

Keywords: jvm JDK Java

Difference
1. String is a constant, StringBuilder, StringBuffer is a variable.
2. The methods and functions in StringBuffer and StringBuilder are completely equivalent.
3. Only the methods in StringBuffer mostly adopt synchronized keywords to modify, so they are thread-safe.
StringBuilder, without this modification, can be considered thread insecure.
4. In a single-threaded program, StringBuilder is more efficient because it does not require locking and does not have multithreaded security.
StringBuffer, on the other hand, needs to judge locks every time, which is relatively inefficient.

Implementation of String+in JVM
StringBuffer started with JDK 1.0
StringBuilder started with JDK 1.5
Starting with JDK 1.5, connection operations with string variables (+) are adopted internally in JVM.
StringBuilder implements this operation, which was previously implemented using StringBuffer.

Principle of StringBuilder Implementation

StringBuilder class inherits from AbstractStringBuilder Abstract class, implements Serializable serialization interface and CharSequence interface.

AbstractStringBuilder abstract class implements Appendabel, CharSequence interface.

Get the corresponding total capacity and used capacity by length() and capacity

Initialization and Expansion Mechanism of StringBuilder
1. The initial capacity of StringBuilder () is 16 characters. When the length of the character stored by the object's entity is greater than 16, the entity capacity increases automatically.
2.StringBuilder(int size) can specify the number of characters specified by the initial capacity parameter of the entity assigned to the object as the parameter size. When the length of the character sequence stored by the entity of the object is greater than size, the capacity of the entity increases automatically. To store the added characters.
3.StringBuilder(String s) can specify the initial capacity of an object's entity as the length of the parameter string s plus 16 additional characters. When the length of the character sequence stored by the entity of the object is longer than size, the capacity of the entity increases automatically to store the added characters.

Expansion algorithm:
When append() method is used to append something after a string, if the length exceeds the size of the string storage space, it needs to be expanded: build a new string with larger storage space and copy the old one;
The specific algorithm is to call the method in AbstractStringBuilder.

When append is added, the size of the append is calculated first and then the size of the string is passed into a method: ensure CapacityInternal, which is used to judge whether the append is expanded or not. If the append is needed, call the new CapacityInternal method to expand it.
Try to expand the new capacity to twice the size of + 2 if to judge if the capacity is not enough, expand directly to the required capacity size.


Principle of StringBuffer Implementation
StringBuffer also inherits AbstractStringBuilder, but it adds the synchronized keyword when rewriting the method of the parent class, making StringBuffer's method thread-safe.


String usage scenarios:

public static void main(String[] args) {  
        /** 
         * Scenario 1: String pool 
         * JAVA There is a string pool in the virtual machine (JVM), in which many String objects are stored. 
         * And it can be shared, so it improves efficiency. 
         * Because the String class is final, its value cannot be changed once it is created. 
         * The string pool is maintained by the String class, and we can call the intern() method to access the string pool.  
         */  
        String s1 = "abc";     
        //_Create an object in the string pool  
        String s2 = "abc";     
        //_String pool already exists object "abc" (shared), so create 0 objects, cumulative create an object  
        System.out.println("s1 == s2 : "+(s1==s2));    
        //_true points to the same object.  
        System.out.println("s1.equals(s2) : " + (s1.equals(s2)));    
        //_Equal true value  
        //↑------------------------------------------------------over  
        /** 
         * Scenario 2: About new String("") 
         *  
         */  
        String s3 = new String("abc");  
        //_Two objects are created, one is stored in the string pool and the other is in the heap area.  
        //_There is also an object reference s3 stored on the stack  
        String s4 = new String("abc");  
        //_The "abc" object already exists in the string pool, so only one object is created in the heap.  
        System.out.println("s3 == s4 : "+(s3==s4));  
        //_The addresses of false S3 and s4 stacks are different and point to different addresses of the stacks.  
        System.out.println("s3.equals(s4) : "+(s3.equals(s4)));  
        //_The values of true S3 and s4 are the same  
        System.out.println("s1 == s3 : "+(s1==s3));  
        //_false stores many different areas, one stack area, one heap area  
        System.out.println("s1.equals(s3) : "+(s1.equals(s3)));  
        //_The same true value  
        //↑------------------------------------------------------over  
        /** 
         * Situation three:  
         * Because constant values are determined (optimized) at compile time. 
         * Here, "ab" and "cd" are constants, so the value of the variable str3 can be determined at compile time. 
         * The compiled effect of this line of code is equivalent to: String str3 = abcd; 
         */  
        String str1 = "ab" + "cd";  //1 objects  
        String str11 = "abcd";   
        System.out.println("str1 = str11 : "+ (str1 == str11));  
        //↑------------------------------------------------------over  
        /** 
         * Situation four:  
         * The local variables STR2 and str3 store the addresses of two detention string objects (intern string objects). 
         *  
         * The third line of code principle (str2+str3): 
         * The runtime JVM first creates a StringBuilder class in the heap. 
         * At the same time, the detention string object pointed to by str2 is used to complete initialization. 
         * Then the append method is called to merge the detention strings pointed to by str3. 
         * Then call the toString() method of StringBuilder to create a String object in the heap. 
         * Finally, the heap address of the newly generated String object is stored in the local variable str3. 
         *  
         * str5 stores the address of the detained string object corresponding to "abcd" in the string pool. 
         * str4 It's certainly different from str5 address. 
         *  
         * There are actually five string objects in memory:  
         *       Three detention string objects, one String object and one StringBuilder object. 
         */  
        String str2 = "ab";  //1 objects  
        String str3 = "cd";  //1 objects                                         
        String str4 = str2+str3;                                        
        String str5 = "abcd";    
        System.out.println("str4 = str5 : " + (str4==str5)); // false  
        //↑------------------------------------------------------over  
        /** 
         * Situation five: 
         *  JAVA The compiler optimizes string + basic types / constants by directly evaluating them as constant expressions. 
         *  The addition of two string s during runtime generates new objects, which are stored in heap. 
         */  
        String str6 = "b";  
        String str7 = "a" + str6;  
        String str67 = "ab";  
        System.out.println("str7 = str67 : "+ (str7 == str67));  
        //_str6 is a variable and will be resolved at run time.  
        final String str8 = "b";  
        String str9 = "a" + str8;  
        String str89 = "ab";  
        System.out.println("str9 = str89 : "+ (str9 == str89));  
        //_str8 is a constant variable and compile time is optimized  
        //↑------------------------------------------------------over  
    } 

Posted by nati on Mon, 06 May 2019 00:15:39 -0700