coffeeak
coffeeak

Reputation: 3120

Number of String objects created

How many String objects will the following code produce?

String s1="Hello"; //"Hello" is in String Pool Object #1
String s2 = s1.substring(2,3);//String object #2
String s3 = s1.toString();
String s4 = new StringBuffer(s1).toString(); //String Object #3

This is the question to one practice Java book I am reading. There is no answer, so I am not sure if my answer is right. Are there 3 or 5 string objects created? Does toString() create a new String object? I looked up online and found that toString() "Returns a string representation of the object". I don't quite understand what this means.

Upvotes: 0

Views: 1650

Answers (5)

rai.skumar
rai.skumar

Reputation: 10667

It will create 3 String object. toString() method implementation of String class prints the content; it doesn't create any new object.

Upvotes: 0

Recurse
Recurse

Reputation: 3585

The answer to your question is implementation dependent, and misleading. There may be anywhere from 2 to 4 "String objects" by the end of the code fragment, exactly how many will depend on the JVM, and how aggressively it intern's small strings (if at all). As has been pointed out the JDK documentation specifies String.toString() return the object, so the answer should be "2 or 3"; however, you would be very foolish to rely on this behaviour.

The reason I say this is misleading is that you are never concerned about the "number of String objects". Objects in Java are very light weight, and you are never worried about counting them.

The only qualification I would add is that while you never care about object counts, you do care about references. In the case of Strings, a nasty surprise can be the number of references to the underlying char array. String objects are flyweights that share the char array, and forgetting this can lead to severe memory leaks. A very simple way to exhaust the heap on a java program is to:

while(!multiGBFileEOF) {
    String bigString = readMultiMBString();
    int index = findSmallFeature(bigString);
    String featureOfInterest = bigString.substring(index, index+4);
    featureList.add(featureOfInterest);
}

The featureList should end up being at most a few 10KB's (~1000 list items each * (4-8 bytes for the arrayref + 12-20 bytes for the object + 8-16 bytes for the char array), ie trivial. However because some common JVM implementations share the backing array for Strings generated by substring(), this could end up trying to store the entire file in memory. The solution is to force an explicit copy of the underlying array by calling String copy = new String(featureOfInterest). Here you don't care if copy and featureOfInterest are the same object or not, as long as copy does not alias the char array behind bigString.

Good luck with your learning.

Upvotes: 0

Bhavik Shah
Bhavik Shah

Reputation: 5183

Whenever you use a new keyword to create a string object it will create a new String object no matter the string is already present in the pool of strings

String s1="Hello"; //this will create a new string object and add it to the pool of strings

String s2 = s1.substring(2,3);//String object #2 again creates a string and adds it in the pools of strings
String s3 = s1.toString();//this will not create a new object but simply refer to already existing object in the pool of strings
String s4 = new StringBuffer(s1).toString(); //String Object #3 this will create a new object as you are using new keyword 

an example

public class Main {
    public static void main(String[] args) {
        String s1 = "abc";//created a string and added it to pool of string
        String s2 = "abc";//no need to create a new object
        String s3 = new String("abc");
        System.out.println("s1 = " + s1);
        System.out.println("s2 = " + s2);
        System.out.println("s2 = " + s3);
        System.out.println("s1 == s2? " + (s1 == s2));//proves that the ref refer to same object
        System.out.println("s1 == s3?"+ (s1==s3));
        System.out.println("s1.equals(s2)? " + (s1.equals(s2)));    
  }
}

the output

s1 = abc
s2 = abc
s3 = abc
s1 == s2? true
s1 == s3? false
s1.equals(s2)? true

Upvotes: 3

ruakh
ruakh

Reputation: 183290

It will create three. Your analysis is correct.

Does toString() create a new String object? I looked up online and found that toString() "Returns a string representation of the object".

That's the description for the generic Object.toString, but String overrides it to give more specific behavior. Its version is documented this way:

This object (which is already a string!) is itself returned.

[link]

Upvotes: 7

kosa
kosa

Reputation: 66637

I think you are correct. Number of String objects would be 3 NOT 5.

s1.toString(); javadoc says:

This object (which is already a string!) is itself returned.

new StringBuffer(s1)

creates new String object.

Upvotes: 4

Related Questions