4

Can you please explain why in the following code String and StringBuffer are treated differently and when value is appended in StringBuffer but not in String.

public class MyClass {
    
    public static void main(String args[]) {
        String str = new String("String Rohan ");
    StringBuffer strBfr = new StringBuffer("String Buffer Rohan "); 
        
        strUpdate(str);
        strBfrUpdate(strBfr);
        
        System.out.println(str);
        System.out.println(strBfr);
        
    }
    
    private static void strBfrUpdate(StringBuffer strBfr){
        strBfr.append("Kushwaha");
    }
    
    private static void  strUpdate(String str){
        str += "Kushwaha";
    }
}

Output is as follows:

String Rohan

String Buffer Rohan Kushwaha

Community
  • 1
  • 1
Rohan Kushwaha
  • 738
  • 6
  • 18

6 Answers6

5

In the main method

String str = new String("String Rohan ");

str is a reference(pointer) pointing to some place in the Heap-memory of the Java-JVM. Lets call this place A

str->A

private static void  strUpdate(String str){
    //str here is still pointing to A, but technically this parameter
    //is a copy of the reference of the str pointer in the main-method
    //pointing to the same place in the heap
    //str->A
    str += "Kushwaha";
    // this line is short for str = str + "Kushwaha"
    //what happens here that you create a new String-Object in the heap (B)
    //and assigne the new value "String Rohan Kushwaha" to the new pointer
    //if you print it out now (within this method) you get what you would 
    //expect
    System.out.println(str);
    //will result in "String Rohan Kushwaha"
}

But the str-pointer of the main-method is still pointing to place A in the Heap where still only "String Rohan" is. So once you leave the scope of the method strUpdate(...) the copied pointer (which was reassigned to place B) is deleted.

Hope this helped a bit...

I guess this here is some helpfull input for your understanding

Is Java "pass-by-reference" or "pass-by-value"?

Community
  • 1
  • 1
Rainer
  • 761
  • 5
  • 20
3

In strUpdate method you keep a reference to a String called str:

private static void  strUpdate(String str){
    str += "Kushwaha";
}

When you write str += "..."; It means:

    str = new String(str + "...");

At this point str references the new String, but only in strUpdate method. It's not "taken back" to main.

Gavriel
  • 18,880
  • 12
  • 68
  • 105
2

String is immutable ( once created can not be changed )object.Every immutable object in Java is thread safe ,that implies String is also thread safe . String can not be used by two threads simultaneously.

For example,

String  demo= " hello Rohan " ;
// The above object is stored in constant string pool and its value can not be modified.

demo="Bye Rohan" ;     //new "Bye Rohan" string is created in constant pool and referenced by the demo variable            
 // "hello Rohan " string still exists in string constant pool and its value is not overrided but we lost reference to the  "hello Roahn" string  

On the other hand,

StringBuffer is mutable means one can change the value of the object . The object created through StringBuffer is stored in the heap . StringBuffer has the same methods as the StringBuilder , but each method in StringBuffer is synchronized that is StringBuffer is thread safe .

To help you undrstand more clear the following link has an excellent example http://www.javatpoint.com/difference-between-string-and-stringbuffer which show that the HasCode difference in String but for the String buffer the HashCode is the same. And in your case because the String is not mutable

the strUpdate() method's concatenated value is not added to the main String. So it remained the same.
Hope this answers your question.

Mohammad Faisal
  • 5,783
  • 15
  • 70
  • 117
Moshiour
  • 633
  • 7
  • 20
0

Just to clearly see the difference, for identityHashCode see System#identityHashCode

package example;

public class MyClass {

     public static void main(String args[]) {
            String str = new String("String Rohan ");
        StringBuffer strBfr = new StringBuffer("String Buffer Rohan "); 

            System.out.println("--- String ---");
            System.out.println("Before update: " + System.identityHashCode(str));
            strUpdate(str);
            System.out.println("After update: " + System.identityHashCode(str));
            System.out.println("--- StringBuffer ---");
            System.out.println("Before String Buffer update: " + System.identityHashCode(strBfr));
            strBfrUpdate(strBfr);
            System.out.println("After String Buffer update: " + System.identityHashCode(strBfr));

            System.out.println("--- Final output ---");
            System.out.println(str);
            System.out.println(strBfr);

        }

        private static void strBfrUpdate(StringBuffer strBfr){
            System.out.println("StringBuffer parameter: " + System.identityHashCode(strBfr));
            strBfr.append("Kushwaha");
            System.out.println("StringBuffer object modification: " + System.identityHashCode(strBfr));
        }

        private static void  strUpdate(String str){
            System.out.println("Parameter: " + System.identityHashCode(str));
            str += "Kushwaha";
            System.out.println("Modified (a new String, passed String instance remain same and each modification will produce new String instance): " + System.identityHashCode(str));      }
}

Output(yours will be different):

--- String ---
Before update: 390033781
Parameter: 390033781
Modified (a new String): 1177666623
After update: 390033781
--- StringBuffer ---
Before String Buffer update: 1833642009
StringBuffer parameter: 1833642009
StringBuffer object modification: 1833642009
After String Buffer update: 1833642009
--- Final output ---
String Rohan 
String Buffer Rohan Kushwaha

Also look at what @Rainer mention Java "pass-by-reference" or "pass-by-value"

Community
  • 1
  • 1
bodo
  • 827
  • 6
  • 19
0

When we modify an existing string a new instance of string will be created in the string pool and string reference variable will point to the new literal. Reference to the old literal will be removed.

In your case two literal are created for String. One in main method and another in strUpdate method. Reference variable str in main methods points to “Rohan” (which you actually print in output) and while reference variable str in strUpdate methods points to “Rohan Kushwaha” (if you put a print in this method you will get “Rohan Kushwaha”)

But when we work with StringBuffer as argument of a methods we are actually sending object reference. When we pass object as reference the modification are visible to the calling methods as well. hence we see "Rohan Kushwaha" for string buffer

Manas
  • 86
  • 6
0

As Shriram already stated in his comment: Strings are immutable in Java, once created they can not be changed. This question has been asked on SO many, many times before (here, for example).

Community
  • 1
  • 1
Seth
  • 1,545
  • 1
  • 16
  • 30