wood burning stoves 2.0*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes String literal vs new String() Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "String literal vs new String()" Watch "String literal vs new String()" New topic
Author

String literal vs new String()

Siva Masilamani
Ranch Hand

Joined: Sep 19, 2008
Posts: 385
Hi Sorry for the lengthy post.

I was going through this link and understood quite a bit.But still has some questions.

http://www.javaranch.com/journal/200409/Journal200409.jsp

Lets say a string is created using constructor.

String s=new String("Hello");

So in this case a new String object will be created in the heap without checking the constant pool and the user reference variable is directly pointed towards it right?
also does JVM create a reference for the literal and place it in the constant pool or no reference will be made to constant pool for this literal?

Because i was confused when reading about String from Kathy SCJP book where it has been said that when a new String() is used, an object is created in the heap and the literal is placed in the pool.

But in the link (from the picture 2) there is no reference to the literal from new String("someString").is it because that literal has been already referred from the constant pool or JVM won't create a reference to constant pool for the new operator?

So as per the book the literal will have reference from the constant pool and it can never be garbage collected but in the link it has been said that there is no reference to the object and hence garbage collected.

JVM will look for constant pool during class load time only if the String is created with literals right?If there is new String("text") then JVM won't look for Constant pool during load time?
I am so confused about it.

please explain.

SCJP 6,SCWCD 5,SCBCD 5

Failure is not an option.
Harsh Pensi
Ranch Hand

Joined: Aug 05, 2009
Posts: 67
At class loading time, all string literals will be placed in pool. When you use new String("literal") an object will be created on heap.


SCJP6 - 93% SCWCD5 - 97%
J Westland
Ranch Hand

Joined: Apr 06, 2009
Posts: 40
Maybe this can help a little bit as I was confused too why you have String = "test" and String = new String("test");

Say you have a really long String made by saying String long = {lotsofoftext}; and you want a substring of long.

You then make the substring of long, by saying String sub = long.Substring(start, end); sub is then made by just referring to this really big String. So, we still just have one big String and one substring pointing to a part of it. This is the way Strings can save memory no need to keep making Strings for words you already have.

However...if you says String sub = new String(long.Substring(start, end)); you will get a totally new string that is independent of the String called long that is in the String pool. So now there will be two objects in the String pool, the really long String long, the String sub and on the heap we also have sub as an Object.

Does this make sense?


Woohoo passed SCJP 1.6, that's the theory exam passed now for the practice ;)
Siva Masilamani
Ranch Hand

Joined: Sep 19, 2008
Posts: 385
Hi

thanks for your reply.

I very well understand that creating String using new operator wastes memory.

But i just want to know how java handles the String in the pool.

But my question was if a string is created with new operator does it also place a reference to that literal in the constant pool.(by the way what gets stored inthe constant pool,reference to object created in the heap or the object itself?).

My understanding is, if i create a string using new operator java checks the constant pool for the literal having the same content and creates a new Object in the heap and copy the content to this new object.But if there is no such literal present in the constant pool then it creates new object in the heap and also places a reference to that literal in the pool.

So if this is correct then what happens when i set the reference to null?will it still maintain the reference to literal from constant pool so that the literal will never get GC even it is created using new operator?
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 19073
    
  40

J Westland wrote:You then make the substring of long, by saying String sub = long.Substring(start, end); sub is then made by just referring to this really big String. So, we still just have one big String and one substring pointing to a part of it. This is the way Strings can save memory no need to keep making Strings for words you already have.


This is not true. Unless, the start and end are zero, and the actual end of the very large string respectively, you will get a new string back. There is no reference to the same space within the very large string.


J Westland wrote:However...if you says String sub = new String(long.Substring(start, end)); you will get a totally new string that is independent of the String called long that is in the String pool. So now there will be two objects in the String pool, the really long String long, the String sub and on the heap we also have sub as an Object.


This is not true. As before, unless start and end represent the orignal string back, you will get a new string. This new string is passed to the constructor of the string, and yet another string is created. This second new string is then assigned to the sub reference. Furthermore, since no other reference now points to the response from the substring call, it is eligible for garbage collection. And finally, this operation has no affect on the string pool.

Henry


Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 19073
    
  40

Siva Masilamani wrote:
My understanding is, if i create a string using new operator java checks the constant pool for the literal having the same content and creates a new Object in the heap and copy the content to this new object.But if there is no such literal present in the constant pool then it creates new object in the heap and also places a reference to that literal in the pool.


When you call the new operator, java will instantiate an object for you, which you can assign to a reference. It should have absolutely no affect on the string pool. This behavior is no different when instantiating any other class type with the new operator.

Henry
J Westland
Ranch Hand

Joined: Apr 06, 2009
Posts: 40
Hi Henry I discussed this with a C++ programmer...he thought I was correct but...that must be one of those things that IS pretty different between languages time to review that part of the book again...
Siva Masilamani
Ranch Hand

Joined: Sep 19, 2008
Posts: 385
When you call the new operator, java will instantiate an object for you, which you can assign to a reference. It should have absolutely no affect on the string pool. This behavior is no different when instantiating any other class type with the new operator.


So you meant that no reference will be made to constant pool apart from user variable reference?.

If so then it contradicts the concept explained in Kathy's SCJP6 book in the page 434 where she explained that

if a string is created using new operator then actually two objects are created and then she stated that java will create a new object in the normal pool memory and make a reference to user then places the literal in the pool?

But what i read is even string objects are created in the heap and only the reference are stored in the constat pool?

I was going thrugh this link and also SCJP book but feel somewhat contradict to each other or i may misunderstood what they are trying to tell us.
http://www.javaranch.com/journal/200409/Journal200409.jsp

Again i am just curious to know how java handle String and i am not going to use new operator in my code unless needed.

Please explain.

Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 19073
    
  40

if a string is created using new operator then actually two objects are created and then she stated that java will create a new object in the normal pool memory and make a reference to user then places the literal in the pool?


You have to separate two different concepts...



The string literal "hello" is handled by the JVM, by creating on string object on the heap, and having a reference to it from the string pool (first time encountered, of course).

The new operator, used in the expression has no effect on the string pool. It merely takes the string object, whose reference is passed in the constructor, and create a new object. It just so happens that the string being passed to the constructor is a literal (which does use the string pool), but it doesn't have to be.


But what i read is even string objects are created in the heap and only the reference are stored in the constat pool?


Correct, the string pool is just a pool of references. There are no string objects in the pool.

Henry
Siva Masilamani
Ranch Hand

Joined: Sep 19, 2008
Posts: 385
Many thanks for taking your time for me,Henry

Now i am clear about this concept.

Willem Kokke
Greenhorn

Joined: Sep 25, 2009
Posts: 2
Siva:

In java every object instance is on the heap, so every String instance is as well. However if you have a string literal, or string constant in your source code, java will during compilation gather all of them and pre-create them (on the heap) and store references to them in the string literal pool.

The advantages of this are

  • Duplicates are removed, because strings are immutable they can safely be shared. This means less overall memory usage.
  • You can safely compare them with == instead of the more expensive equals, since they are guaranteed to be the same instance


  • The disadvantage of this is:

  • References to the strings in the string literal pool are kept for the duration of the program. This means they will never be garbage collected. If you have large string literals, that you only use temporarily, this might actually increase memory usage of your program, but this is hardly ever anything to worry about


  • Now if you create a string with new String("bla") it will not be added to the string literal pool, but it will be created as a new object on the heap. This means you cannot compare it with == any longer, you have to use equals() (if content equality is what you are looking for)

    Short recap:

    string literals and string constants will always be referenced in the string literal pool, and wont be duplicated, and can't be garbage collected
    using new String("bla") will always create a new object on the heap, (so can be duplicated) but then can be garbage collected if no longer used.

    One small addition (no idea if it is in scjp, I have never done that) is the String.intern() function.

    If you do want to add a string to the string literal pool at runtime ( so after creating it with new String() constructor ) you can do that with String.intern

    String.intern will return a reference to a string in the string pool if it already exists. Else it will add the current string to the string pool, and return a reference to itself.


    String s1 = "bla";
    String s2 = new String("bla");
    s2 = s2.intern();

    s1 will be in the string literal pool.
    s2 will initially create a new String instance on the heap. There are now 2 string instances containing the value "bla" in memory
    After the intern call, s1 and s2 will point to exactly the same object instance. (and the instance created by the new String("bla") will be garbage collected eventually)

    Hope that helps!

    Willem

    Willem Kokke
    Greenhorn

    Joined: Sep 25, 2009
    Posts: 2
    Henry Wong wrote:
    J Westland wrote:You then make the substring of long, by saying String sub = long.Substring(start, end); sub is then made by just referring to this really big String. So, we still just have one big String and one substring pointing to a part of it. This is the way Strings can save memory no need to keep making Strings for words you already have.


    This is not true. Unless, the start and end are zero, and the actual end of the very large string respectively, you will get a new string back. There is no reference to the same space within the very large string.
    Henry


    Actually, while the terminology Jawine used might not be 100% exact, the gist of what she says is true. As a speed optimisation, the java.lang.String.substring implementation shares the underlying char buffer, and simply stores an offset and length into the substring.

    Substring returns itself if it is passed 0 for beginIndex and length() for endIndex.
    For any other valid values it will return a new String object, which shares the underlying char[] (which is where most of the memory is)

    You can verify this yourself by reading the code at http://www.docjar.com/html/api/java/lang/String.java.html
    specifically look at substring() on line 1941, which calls the private constructor on line 644

    So yes, if you create a substring from a very long string, the substring will be a new String instance, referring to the same immutable char[] as the long string, but with an offset and length specified that is taken into account in all other operations on that substring.
    For all intents and purposes the memory is shared between them, and whilst the long String object might be garbage collected, the char[] (which has the bulk of the memory associated with it) will not as long as the substring refers to it!

    Henry Wong wrote:
    J Westland wrote:However...if you says String sub = new String(long.Substring(start, end)); you will get a totally new string that is independent of the String called long that is in the String pool. So now there will be two objects in the String pool, the really long String long, the String sub and on the heap we also have sub as an Object.


    This is not true. As before, unless start and end represent the orignal string back, you will get a new string. This new string is passed to the constructor of the string, and yet another string is created. This second new string is then assigned to the sub reference. Furthermore, since no other reference now points to the response from the substring call, it is eligible for garbage collection. And finally, this operation has no affect on the string pool.
    Henry


    Once again, looking at the source code for the String constructor taking another string (line 163), we see that it makes a an actual copy of only that part of the original string that is needed, so Jawine was right about that. This then does allow all memory associated with the long string to be garbage collected. (as the substring will only contain a char[] large enough for that substring, an no longer a reference to original long strings char[])

    You were right about the fact that it does not get added to the string literal pool.

    Henry Wong
    author
    Sheriff

    Joined: Sep 28, 2004
    Posts: 19073
        
      40

    Actually, while the terminology Jawine used might not be 100% exact, the gist of what she says is true. As a speed optimisation, the java.lang.String.substring implementation shares the underlying char buffer, and simply stores an offset and length into the substring.

    Substring returns itself if it is passed 0 for beginIndex and length() for endIndex.
    For any other valid values it will return a new String object, which shares the underlying char[] (which is where most of the memory is)


    So that's what the private constructor is for! I knew about the constructor, but didn't research what used it...

    Anyway, the part about when a string object is created still holds true... except a new char array for the string isn't created, for the substring method.

    Sorry for the confusion...
    Henry

    Jd Sierra
    Greenhorn

    Joined: Jul 09, 2011
    Posts: 17

    Siva has raised a very good question. In fact I am also confusing in this very much.
    and I would like to thank Henry Wong especially for giving such a nice explanation..
    but still I want to ask some questions to make this thing clear..

    Henry Wong Wrote:
    As before, unless start and end represent the orignal string back, you will get a new string. This new string is passed to the constructor of the string, and yet another string is created. This second new string is then assigned to the sub reference. Furthermore, since no other reference now points to the response from the substring call, it is eligible for garbage collection. And finally, this operation has no affect on the string pool.


    So, this means when we create string object using new operator, two objects are created but none of them is referenced from String Literal Pool..am I? Two things I want to make clear, 1) when we use 'new', how many total objects are created? one/two? 2) when we use new, is any object referred from String Literal Pool?
    About answers, what I am thinking is, answer to 1) is 'two' and answer to 2) is 'if we pass String literal in String constrctor to make String, then and then only one of the two objects created will be referred by String Literal Pool'.
    Am I correct??

    Now, If I am right (or wrong) till now, then what happens in following scenario:



    Now, after first line, one object "abc" will be created and it will be referenced from String Literal Pool as well as it will be referenced by s1.
    What exactly happens after line 2?
    definately, "abc" will be referenced by s2, but which "abc"? will it create new one or just refer previously created on line 1? If it will create new object "abc", then will it be referenced from String Literal Pool?

    article on http://www.javaranch.com/journal/200409/Journal200409.jsp#a1, posts by Henry and SCJP book by Kathy- all leads me to raise above questions which clearly indicates how confuse I am? Please solve it.

    Last but not least,
    Following question raised after reading conversation about substring in above posts.


    I was thinking new object will be created after line 2 containing String "ell" , but after reading above posts, I'm confused a bit. Will it not create new object and just refer to the part of the main String created on line 1? If yes, then if s1 is set to null as on line 4, then at that time what will happen? new object will be created containg substring i.e. Steing "ell"?

    Sorry for long post, but if my all of above doubts will be cleared, I will be very thankful to you people.
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: String literal vs new String()