String s = new String("xyz"). How many objects has been made after this line of code execute?
Asked Answered
S

21

31

The commonly agreed answer to this interview question is that two objects are created by the code. But I don't think so; I wrote some code to confirm.

public class StringTest {
    public static void main(String[] args) {
        String s1 = "a";
        String s2 = "a";
        String s3 = new String("a");
        System.out.println("s1: "+s1.hashCode());
        System.out.println("s2: "+s2.hashCode());
        System.out.println("s3: "+s3.hashCode());
    }
}

The output is:

Application output

Does this mean that only one object was created?

Reaffirm: My question is how many object was created by the following code:

String s = new String("xyz")

Instead of the StringTest code.

Inspired by @Don Branson, I debugged the below code:

public class test {
    public static void main(String[] args) {
        String s = new String("abc");
    }
}

And the result is:

Enter image description here

The id of s is 84, and the id of "abc" is 82. What exactly does this mean?

Stephaniestephannie answered 30/10, 2013 at 1:47 Comment(10)
Have you done any research?Vacate
hashCode != unique object!Deborahdeborath
No, it means that all the objects that were created have a hash code of 97.Jabber
of course,is it too simple? if hashCode!=unique object,then how can i distinguish whether a new object was created。Stephaniestephannie
You can try checking expressions like s1 == s2 and s1 == s3 to find out which of them refer to the same object.Jabber
You have to use a test other than hashcode. Things that are not even logically equal can generate the same hash.Gross
I don't know why anyone really care about the result. It is implementation detail which may changed if the compiler get smart/not-smart enough to optimize out the creation of second string object.Hyperopia
A person might care in the context of a classroom - perhaps this is an exercise from a teacher hoping to illuminate the source of bugs arising from the differences between == and equals().Form
@ghui Only two objects are ever created. I explain below.Inandin
How do you know that which hashcode was called as there are two objects(same). Means when we use new operator then we are giving instruction to JVM to create one object and according to String class implementation Class_Loader will create one. So the hashCode() runs on which object?Mortenson
I
28

THERE ARE ERRORS BELOW DEPENDING ON THE JVM/JRE THAT YOU USE. IT IS BETTER TO NOT WORRY ABOUT THINGS LIKE THIS ANYWAYS. SEE COMMENTS SECTION FOR ANY CORRECTIONS/CONCERNS.

First, this question really asks about this addressed here: Is String Literal Pool a collection of references to the String Object, Or a collection of Objects

So, that is a guide for everyone on this matter.

...

Given this line of code: String s = new String(“xyz”)

There are two ways of looking at this:

(1) What happens when the line of code executes -- the literal moment it runs in the program?

(2) What is the net effect of how many Objects are created by the statement?

Answer:

1) After this executes, one additional object is created.

a) The "xyz" String is created and interned when the JVM loads the class that this line of code is contained in.

  • If an "xyz" is already in the intern pool from some other code, then the literal might produce no new String object.

b) When new String s is created, the internal char[] is a copy of the interned"xyz" string.

c) That means, when the line executes, there is only one additional object created.

The fact is the "xyz" object will have been created as soon as the class loaded and before this code section was ever run.

...next scenario ...

2) There are three objects created by the code (including the interned "a")

String s1 = "a";
String s2 = "a";
String s3 = new String("a");

a) s1 and s2 are just referenced,not objects, and they point to the same String in memory.

b) The "a" is interned and is a compound object: one char[] object and the String object itself. It consisting of two objects in memory.

c) s3, new String("a") produces one more object. The new String("a") does not copy the char[] of "a", it only references it internally. Here is the method signature:

public String2(String original) {
        this.value = original.value;
        this.hash = original.hash;
}

One interned String ("a") equals 2 Objects. And one new String("a") equals one more object. Net effect from code is three objects.

Inandin answered 30/10, 2013 at 2:6 Comment(24)
Dont forget that Strings contains internal char arrays which are objects as well.Kaffir
@Kaffir The object reference for s1 and s2 point to the same object in memory. So, only 1 object is ever created because Java is pass-by-reference. Now, if they were s1 = new String("a") and s2 = new String("a"), then 2 objects are created because the call to new String(..) always produces a new object String reference.Inandin
@Saint Hill I was referring to the objects within the Strings, not the Strings themselves. If you create one String, you will have one String object and one array object.Kaffir
@Kaffir String("a") references the char[] of the passed String and does not copy it. So the only object created is the String object itself and not the contents.Inandin
check the title of this question?Stephaniestephannie
@Saint Hill, You are correct, that would mean that if you had only one line of code reading new String("a") then three objects would be created rather than four.Kaffir
Its really pedantic of me though and pretty much not what the question was really asking :PKaffir
@ghui Damn tricky of you :) After this, String s = new String(“xyz”) only one object is created. The interned "xyz" was created or interned when the class loaded. But the new String("xyz") only creates one object because the char[] is referenced internally in the new String.Inandin
Actually,I think 2 objects are created.one is the interned "xyz" the other is created by new String("xyz") which referenced the interned "xyz" in some ways,because new String("xyz") will always created a new object.Stephaniestephannie
Yes, but the "xyz" will be created even if the code section it is contained in does not run. Because, all string literals in code are loaded when the class is loaded, not when the code runs. Your question asks, "...when this line executes? not "by this code". So, 2 if by code, but only 1 when line executes.Inandin
Aha, but its how many objects have been created after that line executes, which by no means excludes class loaded objects or even core VM objects! That probably puts the answer up at 100+... being technically correct is the most fun correct, and this convo is the best.Kaffir
Here I wanna to go further about the reference you described above!Details: String s= new String("xyz"); 1. "xyz" will be created when the class is loaded. And "xyz" references the char[] of the passed String ,here is the first reference 2. new String("xyz") will create a new object which references "xyz" which was created in step 1,here is the second reference.Stephaniestephannie
3. String s =...,which means the local variable s references the object created in step 2. I think the first and second reference are different from the third reference listed above.can u give me some deeper explains,specially the second reference described in step 2.I will not know how to express my gratitude for u!Looking forward to your reply!Stephaniestephannie
A reference in code is not an object. s1,s2,s3 are in the machine code telling the machine where to find the object. They are not objects themselves. More that one reference can point to the same object. The only object you are creating after the class is loaded is the new String("a") or new String("xyz"). The Strings are Objects the s1,s2,s3 merely point to them in your local code.Inandin
yeah,but what I want to ask is whether the object created by new String("xyz") will references the literal "xyz".is it?Stephaniestephannie
Oh GOD! every drop of Java has its own ocean.Sailmaker
Hi Saint can you please explain little more about point 2)[ There are three objects created by the code (including the interned "a")], Here I can understand that 'a' in intern in String pool but why here other object is created for character array? As per my understanding as char[] is only created in String s = new String() constructor. please correct me if i am wrong.Maggio
Even the 'A' that is interned also has a backing char[]. But since String is immutable, when 'new String("A") it just uses the same reference, but still creates a new String object (2+1)=3. But in JDK 9 this is changing and there will now be a byte[] and character encoding instead of a char[]. Still 3 objects though.Inandin
This is not correct. In all versions of HotSpot I’ve checked, the String instance representing a literal ("abc") was created on the first use, so assuming that no-one has used "abc" before, it is created exactly at the String s = new String("abc"); line, rather than class loading time. By the way, whether the internal array is shared or not, depends on the JRE version. Before 1.7.0_06, the array was copied in the String(String) constructor.Shockproof
Are you referring to this: https://mcmap.net/q/471574/-string-pool-vs-constant-pool ?Inandin
You can detect whether a JRE resolves string constants lazily or on load time, as demonstrated by this answer.Shockproof
Too busy right now. I give you full permission to edit my answer.Inandin
Perhaps I’ll do later, but it would be more than a simple change. I just noticed another contradicting point, in 2)c) you state that the String(String) constructor does not copy the array, but shares the reference, whereas in 1)b) you say that it will copy the array. Both behaviors exist, depending on the actual JRE version…Shockproof
I realize now the entire thing is a fiasco. I thought I knew this stuff like anyone else and now I realize I'm full of sh!t. LOL. #javalife THANKS FOR SPOTTING THIS. YOU ARE PROLIFIC AND I AM HUMBLED.Inandin
D
11

Two objects will be created for this:

String s = new String("abc");

One in the heap and the other in the "string constant pool" (SCP). The reference s will pointing to s always, and GC is not allowed in the SCP area, so all objects on SCP will be destroyed automatically at the time of JVM shutdown.

For example:

Here by using a heap object reference we are getting the corresponding SCP object reference by call of intern()

String s1 = new String("abc");
String s2 = s1.intern(); // SCP object reference
System.out.println(s1==s2); // false
String s3 = "abc";
System.out.println(s2==s3); //True s3 reference to SCP object here
Dextrocular answered 8/12, 2014 at 15:22 Comment(2)
@PeterMortensen I don't get it how 2 are created as per your example. you did s1.intern(). as per java docs. "When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned." so you are only adding the value to the pool after calling the intern method not at the time of creating new String.Bridegroom
Downvoted because this answer doesn't distinguish between String instance creation at class-load-time and at statement-execution-time.Innes
M
3

There are two ways to create string objects in Java:

  1. Using the new operator, i.e.

    String s1 = new String("abc");
    
  2. Using a string literal, i.e.

    String s2 = "abc";
    

Now string allocation is costly in both time and memory so the JVM (Java Virtual Machine) performs some tasks. WHAT TASKS?

See, whenever you are using the new operator the object is created, and the JVM will not look in the string pool. It is just going to create the object, but when you are using the string literals for creating string objects then the JVM will perform the task of looking in the string pool

I.e., when you write

String s2 = "abc";

the JVM will look in the string pool and check if "abc" already exists or not. If it exists then a reference is returned to the already existing string "abc" and a new object is not created and if it doesn't exists then an object is created.

So in your case (a)

String s1 = new String("abc");
  • Since new is used the object is created

(b)

String s2 = "abc";
  • using a string literal an object is created and "abc" is not in the string pool and therefore the object is created.

(c)

String s2 = "abc";
  • Again using a string literal and "abc" is in the string pool, and therefore the object is not created.

You can also check it out by using the following code:

class String_Check
{
    public static void main(String[] n)
    {
        String s1 = new String("abc");
        String s2 = "abc";
        String s3 = "abc";
        if (s1==s2)
            System.out.println("s1==s2");
        if(s1==s3)
            System.out.println("s1==s3");
        if(s2==s3)
            System.out.println("s2==s3");
    }
}

I hope this helps... Note that == is used to see if the objects are equal and the equals(Object) method is used to see if content are equal.

Muscarine answered 16/4, 2015 at 12:33 Comment(2)
The JVM doesn't look in the string pool for literals. The compiler and classloader do all that.Pontifical
Downvoted because this answer doesn't distinguish between String instance creation at class-load-time and at statement-execution-time.Innes
S
2

If we execute String s = new String("Brajesh"); , two objects shall be created. One object will be created in string literal pool and another one in heap area. But if we have already same string literal object, then only one object is created. like

String s1  ="Brajesh"; 
String s = new String("Brajesh");//it will create only one object in heap area

Apart from this one additional object is also created in heap area that is char[]'s object. I have attached here snapshot of heap memory. enter image description here

Stripteaser answered 5/7, 2018 at 14:12 Comment(0)
S
2

There are so many random answers and so I am confident that my interviewer will also be not very sure :) :)

I researched a lot and found that hashcode is not the memory address and the variables while debugging don't give the memory address. So, those parameters might confuse.

Struble answered 1/4, 2020 at 22:20 Comment(1)
Unfortunately, there will be quite a few interviewers who are convinced that >they< know the correct answer.Elmerelmina
R
1

2 or 3 objects are created, depending on how smart the compiler is.

Nevertheless, your test is junk, because hashCode of Strings is based on the content of the String, and not on their identity. If you want to check for identity, you should use System.identityHashCode or just == comparison.

The compiler and the runtime are allowed (not forced) to optimize string creation whenever possible. So, they optimize literal strings, by using a single literal for the three strings you have. Anyway, the new operator must return a new object (i.e. a newly allocated one). String optimization at runtime is possible if the static method String.valueOf is used instead. But I don't know if any caching is actually applied by current JREs (maybe it's more expensive to check a hash table than to just allocate a new String)

Rilke answered 30/10, 2013 at 1:58 Comment(3)
Also, please note that System.identityHashCode might still be prone to collisions.Rilke
It doesn't depend on how smart the compiler is, and it is forced, not merely allowed. The compiler's behaviour is mandated in the Java Language Specification.Pontifical
Downvoted because this answer doesn't distinguish between String instance creation at class-load-time and at statement-execution-time.Innes
P
1
        String s1="Pune";
        String s2="Mumbai";
        String s3="Pune";
        String s4=new String("Mumbai");
        System.out.println("S1 :"+s1.hashCode());  //S1 :2499228
        System.out.println("S2 :"+s2.hashCode());  //S2 :-1979126203
        System.out.println("S3 :"+s3.hashCode());  //S3 :2499228
        System.out.println("S4 :"+s4.hashCode());  //S4 :-1979126203
        System.out.println(s2==s4);     // false

As we can see in the above program we are getting a similar hashcode for s2 and s4 respectively although we are getting false using == operator. == operator is used for reference comparison.

Two objects have been created at "String s4=new String("Mumbai")", one in heap memory and one in stack memory. Therefore s2 compares with s4 which is created in heap memory, not with stack memory.

Pinta answered 18/10, 2016 at 15:12 Comment(2)
Objects are not created in stack memory.Pontifical
One object is created in heap and another object was created in String_Constant_Pool(it is in heap)Mortenson
D
1
public String(String original) {
    int size = original.count;
    char[] originalValue = original.value;
    char[] v;
    if (originalValue.length > size) {
        // The array representing the String is bigger than the new
        // String itself.  Perhaps this constructor is being called
        // in order to trim the baggage, so make a copy of the array.
        int off = original.offset;
        v = Arrays.copyOfRange(originalValue, off, off+size);
    } else {
        // The array representing the String is the same
        // size as the String, so no point in making a copy.
        v = originalValue;
    }
    this.offset = 0;
    this.count = size;
    this.value = v;
}

If we see the code , we can see it will just create a char[] and it will get copied every time with same content get instantiated and yes it will store data in String Constant Pool . 1)Will take from SCP String s1 = "a" String s2 = "a"; 2)Creates a new object String s3 = new String("a"); Curiosity , New Object String s2=new String("a"); In all above code same char[] will get copied.i:e char[] value You can check here

Derry answered 13/5, 2017 at 16:8 Comment(0)
F
0

I ran it in the Eclipse debugger. In that context, two objects are created, one with the id 17, the other 22:

enter image description here

Form answered 30/10, 2013 at 1:59 Comment(6)
thanks for your answer ,and can the id represent a unique identifier of an object in the heap memory?Stephaniestephannie
No, don't depend on it for that. To save space JVMs can use a single identical store objects with more than one refer pointed to it, as we see here with s1 and s2. Besides, you'd be depending on implementation details of the JVM, and that's fraught with peril.Form
It's part of the JVM's internal mechanism for tracking objects. It's not something that you would ever rely on in code. It's significant here simply because it illustrates that the final String allocation does not use the same object, and therefore causes different results depending on whether you're using == or .equals(), a fairly common source of bugs, unless you're using something like Sonar.Form
It is not an implementation detail. Pooling of string literals is required by the Java Language Speification.Pontifical
Right, a difference choice of words in the comment would be good. Depending on that behavior as a common practice can lead to hard-to-find bugs. At the time (not sure what Java's doing these days) the JVM could in certain cases store the same string literal in more than one location. For example, this would happen during deserialization and cause issues. The main point is to be careful depending on this behavior, since implementations can have bugs causing them to differ from the spec.Form
@DonBranson: when deserializing a string, it is not a literal anymore, even if it was when serializing. So it’s not correct to say that “the JVM could … store the same string literal in more than one location”. There are simply operations that do not guaranty to return the same string instance you’ve passed in. So relying on the identity of string instances is indeed a bad thing in most cases, regardless of whether the original instances were representing literals or not.Shockproof
S
0

java.lang.String overrides the hashCode() method so that the value depends on the content of the string.

As a result, hashCode() does not tell you anything about the number of instances. It may be the same string or may be another instance with no single byte shared. Same about equals(). This explains your output.

Use System.identityHashCode(..) for this kind of research.

And may the source be with you.

Session answered 1/10, 2015 at 11:12 Comment(0)
M
0

@Giulio, You are right. String s3 = new String("abc"); creates two objects one in heap with reference s3 and another in SCP(Without reference). and now String s2 = "abc"; doesn't create any new object in SCP because "abc" is already there in SCP.

    String s1 = "abc";
    String s2 = "abc";
    String s3 = new String("abc");
    String s4 = s3.intern();
    System.out.println("s1: "+System.identityHashCode(s1));
    System.out.println("s2: "+System.identityHashCode(s2));
    System.out.println("s3: "+System.identityHashCode(s3));
    System.out.println("s4: "+System.identityHashCode(s4));

O/P:s1: 366712642, s2: 366712642, s3: 1829164700, s4: 366712642

As i am not eligible for commenting i wrote it here.

Magnifico answered 12/1, 2018 at 7:39 Comment(0)
S
0

If we run below code in eclipse in debug mode we'll get an idea about how many objects are created with String string = new String("manoj"); Internally it will create String str = "manoj"in String class constructor. Just check id after hover on reference as shown in below screen shot. ScreenShot

public static void main(String[] args)
{
    String str = "atul";
    String string = new String("manoj");
    String string2 = "manoj";
    System.out.println(str == string);
}
Sibeal answered 18/9, 2018 at 12:56 Comment(0)
D
0

Confused with what exactly happens after the new String("<>") is being called, I found this thread. Your hashcode comparison understanding is not technically correct though.

int hashCode() has been overriden in String class and it returns a value depending on the content of the String literal.

String s1 = new String("Hello"); String s2 = new String("Hello");

So s1.hashCode() = s2.hashCode() = anyStringOfContent_"Hello".hashCode()

**/** Cache the hash code for the string */
private int hash; // Default to 0
public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;
        for (int i = 0; i < value.length; i++) {
            **h = 31 * h + val[i];**
        }
        hash = h;
    }
    return h;
}**

Now just to explain why is this done, you can actually read the Kathy Sierra book which has a great explanation why developers have done in this manner (basically any objects returning true to equals() method should return same hashCode() value).

Dickerson answered 15/11, 2018 at 21:24 Comment(0)
Z
0

If new String() creates 2 objects (one in heap and one in String pool) then what is the use of .intern method ?

intern() method invoked on a String object looks for the string contained by this String object in the pool, if the string is found there then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.

Zelaya answered 5/2, 2019 at 5:42 Comment(1)
new String()only creates one object. new String("literal") does create one or two objects. (It depends on whether the string object for "literal" has already been created.) The purpose of intern() is to deal with strings that are created in other ways; e.g. from a char array or byte array or by a String method.Elmerelmina
A
0

2 objects made out of:

String s = new String("xyz");

1st creating new String object in heap memory (String Pool)

2nd placing "xyz" in string constant pool

Averse answered 27/12, 2020 at 10:35 Comment(0)
B
0

It creates 2 Objects . We can debug and see . sting constructor debugged . When we pass value as new String("XYZ") the constructor involved created a Object for original variable. Observe id=26 .

Now the String S1 id is different in String S1 = new String("XYZ"); but String s2 = "XYZ" id will be same as original variable also reference address of Objects are different and S1.intern and S2 has same reference address . So 2 Objects are getting created one in SCP (because intern and literal are referring same Object) and one in Heap. String creation

Barge answered 16/5 at 17:34 Comment(0)
L
-2

There is a concept called string pool in Java. A string pool (string intern pool) is a special storage area in the Java heap. When a string is created and if the string already exists in the pool, the reference of the existing string will be returned, instead of creating a new object and returning its reference.

So String s = new String(“xyz”) it will create two objects.

  1. The first object will be created in the Java permanent heap memory as part of the argument we are passing - "XYZ". And it will be created in the String Literal Pool.

  2. The second object will be created within the Java heap memory - which will be created as part of the new operator.

Lactic answered 1/7, 2015 at 10:56 Comment(1)
Downvoted because this answer doesn't distinguish between String instance creation at class-load-time and at statement-execution-time.Innes
H
-3

Just because all your hash codes are the same does not mean that you are looking at the same object. Two objects are created. Let's break this down.

String s = new String(“xyz”);

In the part ' new String("xyz") ', an address is returned to the new string "xyz". When you say ' String s = ', this assigns that returned address to this object, so that they point to the same place, but the new string and string s are two seperate objects.

Haemolysin answered 30/10, 2013 at 2:1 Comment(4)
but 's'is just a Reference variable and it points to the Object which is created by the expression 'new String("xyz")' in the heap memory. so i still think only one Object was created .what's wrong with my thought.correct it please.Stephaniestephannie
I suppose that you could call 's' a reference value in the way that strings are always passed by reference in Java. As for whether this means only one object is involved? I am not an expert in java, and i will be the first to tell you that. However, in my eye even though 's' is a "reference variable", it is also still an object, because it is a string, which extends class 'Object' ;)Haemolysin
It may also be possible that you are technically correct in some sense of a deeper understanding of how compilers work or the underpinnings of memory management etc, but that most people see both parts of that line of code as objects.Haemolysin
Two objects can't be in the same place. Answer doesn't make sense.Pontifical
A
-3

I used the hashcode() method to find the number of string objects created. The hashcode() method digests the data stored in the reference variable into a single hash value.

CASE1:

String s="

Fred";
System.out.println(s.hashCode());

s=s+"47";
System.out.println(s.hashCode());

s=s.substring(2,5);
System.out.println(s.hashCode());

s=s.toUpperCase();
System.out.println(s.hashCode());

s=s.toString();
System.out.println(s.hashCode());

The output is:

Fred--2198155         //1st object ----------------  String s="Fred"

Fred47--2112428622    //2nd object ----------------  s=s+"47"

ed4--100213           //3rd object ----------------  s=s.substring(2,5)

ED4--68469            //4th object ----------------  s=s.toUpperCase()

ED4--68469            //this is retrieved from the string constant pool -------- s=s.toString();

So 4 objects created in total.

CASE 2:

String s="FRED";
System.out.println(s.hashCode());

s=s+"47";
System.out.println(s.hashCode());

s=s.substring(2,5);
System.out.println(s.hashCode());

s=s.toUpperCase();
System.out.println(s.hashCode());

s=s.toString();
System.out.println(s.hashCode());

The output is:

FRED--2166379       //1st object ----------------  String s="Fred" 

FRED47--2081891886  //2nd object ----------------  s=s+"47"

ED4--68469          //3rd object ----------------  s=s.substring(2,5)

ED4--68469          //this is retrieved from the string constant pool -------  s=s.toUpperCase()

ED4--68469          //this is retrieved from the string constant pool -------- s=s.toString() 

3 objects created in total.

Amphictyony answered 20/11, 2015 at 13:8 Comment(1)
Two equal (but not identical) strings will always have the same hashcode... What you describe does not prove anything I'm afraid...Gamete
C
-3

There is a way to find how many objects are created using the new keyword (String s1=new String("Rajesh")).

public class Rajesh {
    public static void main(String[] args){
        String s1=new String("Rajesh");
        System.out.println(s1+s1.intern());
    }
}

Output:

RajeshRajesh //s1=Rajesh+s2.intern()=Rajesh

Note: As we know the intern method always hit the string constant pool of heap memory.

Chirrupy answered 9/2, 2017 at 9:20 Comment(1)
The question is not about printing the String in to console.Mortenson
T
-3

String s = new String("xyz");

how many objects has been created in above code?

Only one object has been created in above code, that's in heap memory.

not two object.....

If two objects are created, one is in a heap memory(new operator) and another one is in String constant pool(string literal), if your store below value using String literal ,

String s1 = "xyz";

it will not returns reference of object s in string constant pool. it will create new object in String Constant Pool as s1.

How?

we can check it by using == operator (s == s1) to check the reference type. If s is already stored in String Constant Pool it give the true, in this case output is false.

So the conclusion is one object is created in above code.

Telpher answered 24/10, 2018 at 14:29 Comment(1)
There is no "constant pool" or "string constant pool" in the JVM. There is a string pool, but it is part of the regular heap ... from Java 7 onwards.Elmerelmina

© 2022 - 2024 — McMap. All rights reserved.