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?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
smileVann
  • 554
  • 1
  • 6
  • 15

20 Answers20

27

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.

The Coordinator
  • 13,007
  • 11
  • 44
  • 73
  • 1
    Dont forget that Strings contains internal char arrays which are objects as well. – Numeron Oct 30 '13 at 02:16
  • @Numeron 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. – The Coordinator Oct 30 '13 at 05:34
  • @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. – Numeron Oct 30 '13 at 05:44
  • @Numeron `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. – The Coordinator Nov 04 '13 at 03:17
  • check the title of this question? – smileVann Nov 04 '13 at 07:28
  • @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. – Numeron Nov 04 '13 at 07:34
  • Its really pedantic of me though and pretty much not what the question was really asking :P – Numeron Nov 04 '13 at 07:48
  • @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`. – The Coordinator Nov 04 '13 at 08:22
  • 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. – smileVann Nov 04 '13 at 08:40
  • 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. – The Coordinator Nov 04 '13 at 08:42
  • 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. – Numeron Nov 04 '13 at 08:50
  • 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. – smileVann Nov 10 '13 at 08:07
  • 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! – smileVann Nov 10 '13 at 08:09
  • 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. – The Coordinator Nov 10 '13 at 08:14
  • yeah,but what I want to ask is whether the object created by `new String("xyz")` will references the literal "xyz".is it? – smileVann Nov 10 '13 at 08:55
  • 4
    Oh GOD! every drop of Java has its own ocean. – KNU Nov 18 '14 at 11:05
  • 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. – Jekin Kalariya Dec 14 '16 at 12:30
  • 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. – The Coordinator Dec 14 '16 at 13:16
  • 2
    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. – Holger Nov 21 '17 at 10:57
  • Are you referring to this: https://stackoverflow.com/a/23253122/1584255 ? – The Coordinator Nov 21 '17 at 12:10
  • You can detect whether a JRE resolves string constants lazily or on load time, as demonstrated by [this answer](https://stackoverflow.com/a/44929935/2711488). – Holger Nov 21 '17 at 17:48
  • Too busy right now. I give you full permission to edit my answer. – The Coordinator Nov 22 '17 at 23:32
  • 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… – Holger Nov 23 '17 at 11:03
  • 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. – The Coordinator Nov 24 '17 at 11:57
10

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
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user2663609
  • 407
  • 7
  • 10
  • @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. – Kid101 Dec 26 '17 at 11:19
  • Downvoted because this answer doesn't distinguish between String instance creation at class-load-time and at statement-execution-time. – Ralf Kleberhoff Feb 26 '18 at 17:12
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.

Valentin Michalak
  • 2,089
  • 1
  • 14
  • 27
Musaddique
  • 443
  • 5
  • 9
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

Brajesh
  • 1,515
  • 13
  • 18
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.

  • 1
    Unfortunately, there will be quite a few interviewers who are convinced that >they< know the correct answer. – Stephen C Dec 22 '20 at 03:56
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)

Giulio Franco
  • 3,170
  • 15
  • 18
  • Also, please note that `System.identityHashCode` might still be prone to collisions. – Giulio Franco Oct 30 '13 at 01:59
  • 1
    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. – user207421 Mar 23 '17 at 05:36
  • Downvoted because this answer doesn't distinguish between String instance creation at class-load-time and at statement-execution-time. – Ralf Kleberhoff Feb 26 '18 at 17:13
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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
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

Samrat Roy
  • 37
  • 9
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

Don Branson
  • 13,631
  • 10
  • 59
  • 101
  • thanks for your answer ,and can the id represent a unique identifier of an object in the heap memory? – smileVann Oct 30 '13 at 02:36
  • 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. – Don Branson Oct 30 '13 at 13:56
  • 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. – Don Branson Nov 03 '13 at 19:25
  • It is not an implementation detail. Pooling of string literals is required by the Java Language Speification. – user207421 Mar 23 '17 at 05:42
  • 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. – Don Branson Mar 23 '17 at 14:03
  • @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. – Holger Nov 21 '17 at 11:08
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.

Audrius Meškauskas
  • 20,936
  • 12
  • 75
  • 93
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.

Siddappa Walake
  • 303
  • 5
  • 14
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);
}
atul_java
  • 16
  • 1
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).

Priyak Dey
  • 1,227
  • 8
  • 20
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.

Rahul
  • 49
  • 1
  • 5
  • `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. – Stephen C Dec 22 '20 at 03:59
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

Fakhar
  • 3,946
  • 39
  • 35
-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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Siddhartha
  • 492
  • 1
  • 5
  • 15
  • Downvoted because this answer doesn't distinguish between String instance creation at class-load-time and at statement-execution-time. – Ralf Kleberhoff Feb 26 '18 at 17:15
-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.

Drifter64
  • 1,103
  • 3
  • 11
  • 30
  • 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. – smileVann Oct 30 '13 at 02:20
  • 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' ;) – Drifter64 Nov 01 '13 at 12:25
  • 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. – Drifter64 Nov 01 '13 at 12:28
  • Two objects can't be in the same place. Answer doesn't make sense. – user207421 Mar 23 '17 at 05:40
-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.

Mike G
  • 4,232
  • 9
  • 40
  • 66
  • 1
    Two equal (but not identical) strings will always have the same hashcode... What you describe does not prove anything I'm afraid... – assylias Nov 20 '15 at 14:25
-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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
-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.

  • 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. – Stephen C Dec 22 '20 at 04:04