Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java String Immutability and Using same string value to create a new string

I know that the title of the question is not very clear, sorry about that, did not know how to put it up. I have a very basic java implementation question which I want to focus on application performance, but it also involves String creation pattern in java.

I understand the immutability concept of Strings in Java. What I am not sure about is that, I have read somewhere that the following will not make two different String objects:

String name = "Sambhav";
String myName= "Sambhav";

I want to know how does Java do that? Does it actually look for a String value in the program memory and check for its existence and if it does not exist then creates a new String object? In that case obviously it is saving memory but there are performance issues.

Also lets say I have a code like this:

  public void some_method(){
        String name = "Sambhav";
        System.out.println(name); //  or any random stufff
  }

Now on each call of this function, is there a new String being made and added to memory or am I using the same String object? I am just curious to know about the insights of how all this is happening?

Also if we say that

String name = "Sambhav";
String myName= "Sambhav";

will not create a new object because of reference, what about

String name = new String("Sambhav");
String myName= new String("Sambhav");

Will Java still be able to catch that the string are the same and just point myName to the same object as created in the previous statement?

like image 810
Sambhav Sharma Avatar asked Dec 19 '22 15:12

Sambhav Sharma


2 Answers

Strings are internally char arrays with some inherent capabilities to work with the underlying char array. Eg. subString(int), split(String) methods.

Strings are immutable which means any effort made to change a String reference create a new String and allocate memory for that. As below

line 1. String a = new String("SomeString");
line 2. a = "SomeStringChanged";

line 1 allocate memory with "SomeString" referenced by variable a and add "SomeString" to String Pool

line 2 allocate memory in String Pool with "SomeStringChanged" and referenced by a. i.e a is not pointing to "SomeString" now and memory occupied by "SomeString" is available for gc now.

No reuse here

line 3. String  b =  "SomeStringChanged";

Now the literal "SomeStringChanged" is reused by variable a and b. i.e they are referring to the same memory location, in fact to a location called the 'String Pool'.

line 4. a = new String("SomeStringChanged");

Now a new allocation is done which contains "SomeStringChanged" and referenced by a

There is no reuse happening now. (the char array SomeStringChanged is already there in String Pool. So no String Pool allocation happen)

line 5. a = new String("SomeStringChanged").intern();

Now the allocation created during line 4 is discarded and variable a and b are referring to same location in the String Pool which contains "SomeStringChanged". There is reuse of the same char array here. The credit goes to intern() method

line 6. String x = new String("SomeX");
line 7. String y = "SomeX";

Line 6 will create an allocation for SomeX in the heap and in String Pool. The char array is duplicated.

Line 7 will not allocate any memory for SomeX since its already there in the String Pool

Line 8 String s = new String(someStringVariable);

Line 8 will only allocate single memory location in the heap and not in the String Pool.

In conclusion the reuse of a char array of string is only possible if a String reference is declared as a literal or the String object is interned i.e Only these two can make use of a String pool (which is in fact the idea behind char array reuse).

like image 56
Kripz Avatar answered May 01 '23 12:05

Kripz


String that you put in quotes in you source files "like that" are compile-time constants and in case their contents match they are represented by a single entry in a constant pool inside your class's byte-code representation and thus represent a single String object at run-time.

String name = new String("Sambhav");
String myName= new String("Sambhav");

Those are different Objects explicitly, a new String Object will created for each call, though it could reuse char array of the underlying string (the one you provide in constructor). This happens due to new keyword that envisages Java to create a new object. And that is why name != myName in that case, even though name.equals(myName)

like image 32
aljipa Avatar answered May 01 '23 10:05

aljipa