• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Jeanne Boyarsky
  • Ron McLeod
Sheriffs:
  • Paul Clapham
  • Liutauras Vilda
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Roland Mueller
Bartenders:

String

 
Ranch Hand
Posts: 18944
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Have a look at the foll. code:
void sop(String s)
{ System.out.println(s);}
if("string".substring(0)=="string")
sop("substring true");
else
sop("substring false");
The answer is true.But i thought the answer is false since
"string".substring(0) returns a new string object.Isnt it???
Correct me where i am wrong.
Thanks!
 
Desperado
Posts: 3226
5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That's because of the "String pool" phenomenon.
The object "string" is in there and as such is the same object compared. SO the bottom line is that I think the API doc is incorrect for just this case.
Good question
 
Anonymous
Ranch Hand
Posts: 18944
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Tony ,Thanks for the immediate reply.But,i didnt get u.The same is the result if i use replace method.Can u explain me in detail.I have little idea about the string pool that if 2 string literals have same value,
they will have same address.
Thanks!

[This message has been edited by avn (edited July 22, 2000).]
 
Ranch Hand
Posts: 116
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
In general, methods in String class do not create a new
String object if the value they must return is same as
current (this) String object. They just return the
current String object (this).
 
Ranch Hand
Posts: 1467
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
avn,
What Tony said is ok. But that is not the WHOLE reason for your qstn. The point to note here is unlike in other wrapper classes , like Integer/Character/Byte/Long.. where the toString() always returns a new object, here in case of String objects, the programmers of Sun decided to return the SAME string object reference for almost all the methods invoked on a string object, provided the result of the operation happened to be SAME as that of the string object on which the method is invoked on.
In other words, if there is a string object (wherher it is in heap memory or String pool , it does not matter), and we invoke a valid String class method like toString()/replace(..)/trim()/toUppercase()/toLowercase/..... on this string object, and if the result of this method invocation happened to return the same result as the string object on which the method is invoked on, for example , then the method will return the SAME ORIGINAL string object ref irrespective of it is in the heap or string pool. Please go through the foll info. carefully.
<pre>

//case 1
String avnStr = new String("avn");
if(avnStr.toLowercase() == avnStr)
System.out.println("true"); //This will be printed
//case 2
String avnStr1 = new String("AVN");
if(avnStr1.toUppercase() == avnStr1)
System.out.println("true"); //This will ALSO be printed
//case 3
String avnStr2 = new String("AVN");
if(avnStr2.toLowercase() == avnStr2)
System.out.println("true");
else
System.out.println("false"); //false will be printed

</pre>
In the above example the first 2 cases , logically thinking when we invoke a toLowercase() on a String, whilc is already fully of lowercase , why should we return a new String object in the heap as a result ? Why waste memory ? Better we return the same original object reference itself whose content is same as that of what this toLowercase() is going to return. right?. This is how I tested and convinced myself and remembered concepts about the String class in Java.
The same holds true for other methods also ,like invoking a toUppercase() on a FULLY UPPER CASE string. Just think of this way. If any string method invoked on a string object does not do any REAL JOB in the process , then the method will return the same object reference as that of the original string object on which the method is invoked on.
I give you another example.

String avnStr="avn";
What if( avnStr.trim() == avnStr )will return?

We know that trim() method trims all front and trailing white spaces (all chars bet \u0000 to \u0020, inclusive of \u0000 and \u00020 ) right?. Now in our example does this trim() really trims anything? No, there is nothing to trim. So the invocation of avnStr.trim() returns the same original object reference,which here is avnStr. It may be in the heap/String poll. It does not matter. The bottonline is the SAME ORIGINAL object reference is returned. So the above code snippet will return true.
On the other hand take the following example.

String avnStr=" avn";
What avnStr.trim() will return?

Here the .trim() method has some REAL WORK TO DO. IT has to trim the spaces at the front and retun a fresh new string object in the heap which is of just 3 chars length , which has content as "avn" and resides in the heap. So I think you can get the picture now. IF you compare now like the foll,
if (avnStr.trim() == avnStr) for the just said case above , it WILL NOT be true for the above explained reason.
The decision of programmers of Sun , who wrote the String class definition source code, to RETURN THE SAME OBJECT REFERENCE if NO REAL WOK IS DONE when any String class method is invoked on a string object , plays a crucial role here. Are you convinced now avn?. Please come back if you have anything to ask.
You can explore more here.
regds
maha anna

[This message has been edited by maha anna (edited July 22, 2000).]
 
Anonymous
Ranch Hand
Posts: 18944
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks! for the explanation Maha.That was very clear.
But, got a doubt again.U said that toString() for Wrapper classes will give new Object.But,is that valid for Boolean classes also, since i tried using the boolean class and it was
behaving in the same way as String class.
Thanks!
 
maha anna
Ranch Hand
Posts: 1467
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
avn,
Yes. yes. Among all the Wrapper classes Boolean class is little different as you found out now. The simple reason is the Boolean class creates a "true" or "false" string literal in String pool and returns this String pool address as opposed to other Wrapper classes which create a NEW STRING OBJECT in the heap everytime .toString() is called. In String pool ALL STRING OBJECTS ARE DISTINCT. Isn't?. Which means in the String pool maximum there can be 1 "true" 1 "false" and so on. If a "true" is not already present, it is created newly first time in the String pool and from next time onwards, the SAME "true" string pool object reference is returned when you call .toString() again on a Boolean object. You get the reasoning now right?. This is the reason for your above finding.
Also there is another interesting topic on this already. Please take a look at this.
See, when we find out something on our own, it is really satisfying . Isn't? I am really glad you did some testing and came back. This is the reason myself have a very strong belief in writing some code and testing.
regds
maha anna

[This message has been edited by maha anna (edited July 23, 2000).]
 
Anonymous
Ranch Hand
Posts: 18944
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
ThankYou! MAHA.That was great explanation.But, i
couldnt get ur point correctly.The problem is i
dont have clear idea about StringPool and objects created in heap.So,can u provide me with a link which gives detailed description about these two topics.
ThankYou.
 
maha anna
Ranch Hand
Posts: 1467
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
avn,
Sorry for the late reply. ( Since you just wanted links , not Maha's Explanation..just kidding..) I give you some helpful discussions on this. There are no particular link for this String pool concept as I am aware of . So, please get some idea from the following discussions , especially from Mr.Jim's posts and feel free to come back. Let us not leave it as incomplete discussion eventhough the detailed concepts of String pool is not included in the SCJP exam.
regds
maha anna
1 Discussion 1
1 Discussion 2
1 Discussion 3
1 Discussion 4
1 Discussion 5
regds
maha anna

[This message has been edited by maha anna (edited July 24, 2000).]
 
Anonymous
Ranch Hand
Posts: 18944
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks! maha for the links.But, i think i am again getting
confused.
Reagrding String s = new String("test");--how does this create
2 objects.And also Pretending for exam String s="string" is not
created in StringPool,but in heap???
Thanks!
 
maha anna
Ranch Hand
Posts: 1467
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
avn,
The String pool concept.( NOT NEEDED FOR SCJP EXAM )
We know what is a String object. It is basically a set of characters like "JavaRanch" where 'J' ,'a' , 'v' , 'a', 'R' ... and so on are all characters.
A String object created in so many ways using the many different constructors of the String class as shown here in the Java API Doc. It can be created from a byte[], char[], another String object itself, another StringBuffer object are few to name here.
All the String constructors shown in the API are used to create a String object in the heap memory using new String(....) format.
So we can further break up the diferent ways to create a String object as one of the following ways.
<pre>

1. String s1 = new String(....);
2. String s2 = "....";

3.String s3 = AStringObject+ something
(the something may be any_primitive/null/true/false/anyObject)
4. String s4 = objref.someMethod(...)
(the someMethod(..) supposed to return a String object as its return value)

</pre>
So, now we know the different ways to create a String object. Next let us see where they are created. There are 2 areas in the memory where String objects are created. They are 1.Heap 2. String pool. ( All objects created in the so called heap memory are eligible for Garbage Collection once the object loses all its references. This is just an add-on info).
A String pool is nothing but a construct which has String objects in it. The important point to note here is ALL the String objects in the String pool are created in one of the following ways.
DIFFERENT WAYS TO CREATE A STRING POOL OBJECT
case 1. using " " (double quotes)
String s1 = "avn"; //case 1
case 2. ADDING ALL compile time constants which are of type String
final String s1 = "avn";
final String s2 = " likes";
final String s3 = " JAVARANCH";
String s4 = s1+s2+s3; //case 2
Since we know Math.PI is another compile time constant. It is static final double. The foll. also composes another String pool object

String s5 = "avn" + Math.PI;
Basically the concept is this. If there is a var whole value is CONSTANT throughout its life time, then A String object's value which is made of these vars , is also going to be constant right?. IN other words we can gurantee that the String's content is NOT going to change at all. When the compiler convinces itself that the String's content is NOT GOING to change at all ,it creates them in the String pool. But look at the following example.
String s1 ="avn";
String s2 ="likes";
String s3 ="Java";
These String references s1,s2,s3 are AT PRESENT pointing to the String objects created in the String pool "avn","likes","Java". But they CAN BE CHANGED VERY well to point to another object right? Then how can the following new String s4 can have a CONSTANT VALUE ? It is not correct right? The difference between final String s1 = "avn"; and just String s1="avn" is the word 'final' which makes the ref s1 to have the CONSTANT VALUE throughout its life time.
String s4 = s1+s2+s3; //s4 is not at all a String pool object, since the individual component s1,s2,s3 are not constants.

Also just blindly remember this. Whenever a compiler sees SOMETHING between " ", it CREATES the String object in String pool. So if you take the following example, there are 3 freash String pool objects created. They are "avn","likes","Java"
String s1 ="avn"; //String pool obj1
String s2 ="likes"; //String pool obj2
String s3 ="Java"; //String pool obj3
Another point to note in case of String pool is there is ONLY ONE DISTINCT object. In other words only one "avn", only one "likes" only one "Java". If you write another set of Strings like the following in the same programme
String s1 ="avn"; //String pool obj1
String s2 ="likes"; //String pool obj2
String s3 ="Java"; //String pool obj3
String s4 ="avn"; //s4 will be = s1
String s5 ="likes"; //s5 will be = s2
String s6 ="Java"; //s6 will be = s3
now the creation of String objects s4,s5 and s6 WILL NOT create any new String pool objects. Instead s4 will point to the SAME address as that of s1, s5 will be same as s2, s6 same as s3. You get the point now. A string pool is just a pool of distinct Strings made from constant valued Strings. So now our String pool has got 3 Strings. Next assume we write the following code in our prog.
String s1 ="avn"; //String pool obj1
String s2 ="likes"; //String pool obj2
String s3 ="Java"; //String pool obj3
String s4 ="avn"; //s4 will be = s1
String s5 ="likes"; //s5 will be = s2
String s6 ="Java"; //s6 will be = s3
String s7 = "avn"+ "likes" + "java";
String s8 = "PI"+ "value=" + Math.PI;
Now our String pool has 2 newcomers who are "avnlikesJava" and "PIvalue=3.14".
At the same time even if you create another String pool object with the same content , but DIFFERENT way, in the same program, like the following
final String s9 = "PI";
final String s10 ="value="
final String s11 =s9+s10+Math.PI; // This stamement WILL NOT create a new Stirng pool object since there is ALREAY ONE in the String pool with the SAME CONTENT as "PIvalue=3.14".
Also note that all the String pool objects are created during compile time itself and the compiler has a table which has the references. So whenever the compiler sees in our code there is a possiblity to create a String pool object, then it creates it and puts the reference in its internal table. So by now our compiler table would have got 7 distinct references.
("avn","likes","java","PI","value=","avnlikesJava","Pivalue=3.14")Got it.
String pool is like a COMMON POOL of String objects, used throughout the program. But once you create a Stirng pool object it lives in memory throughout the JVM. In other words , without knowing the side effects you would have created 100 String pool objects like String name1= "111", String name2="222"...String name100="100". What really happened is there are 100 String pool objects created and there is a internal table created by the compiler which has 100 references in it and ALL these 100 objects CAN NOT be garbage collected until the JVM exits. You might have just used these objects just once or twice. But even if you set the reference to null, it WILL NOT BE garbage collected. For example,
String s1="MAHA";
s1=null; //The String pool object "MAHA" is memory is NOT GC'd.
[ ALso note that in the REAL EXAM all GC qstns are asked with String objects created in the heap which are eligible to GC once an object loses all its refs. ]
case 3. ADDING ALL String literals like "abc" +"cde";
String s5 = "avn" +" likes"+ "JavaRanch"; //case 3

case 4. calling the intern method of a String object.
This is a very interesting concept. As we know there is a String class method called intern(). What it really does is , when we invoke this method on a String object, it volunteers this String object to be a common String pool object. In otherwords,
char[] charArray = {'M','A','H','A'};
String s1 = new String(charArray);
s1.intern();
What this above 3 stmnts do is a String object with content as "MAHA" is created in heap in stmnt 2. The 3rd stmnt tries to CREATE A NEW STRING POOL object whose content is same as that of s1 ref. Now what happens ?
There may be 2 cases. If there would have already existing String pool object with same content as "MAHA", then this intern() method WILL NOT create a NEW ONE as we discussed earlier. So the already existing String pool object "MAHA" 's address is returned by this method.
Another case is if there is NO PRE-EXISTING "MAHA" String pool object, then this intern() WILL CREATE a new "MAHA" String pool object and returns this new address. If you try to again call intern(), this time the JUST CREATED "MAHA" String pool object's address will be returned and NO NEW "MAHA" String pool object will be created.
So having discussed how the String pool objects are created, ALL OTHER WAYS OF creating String objects are CREATED in the heap memory.
Let us take the above 4 cases and analyze.
1. String s1 = new String(....); //obj ref'd by s1 in heap
2. String s2 = "...."; //obj ref'd by s2 in Stirng pool
3. String s3 = AStringObject + something ; //can be anywhere depending upon whether the individual comp's have constant values.
4. String s4 = objref.someMethod(...)
(can be anything depending upon what this method returns. A String pool object or heap object)

I give you some examples to explore. Consider each case as a separate code segment.
case 1:
1. String s1 = "1111";
- only one object / created in the String pool
case 2:
1. String s1 = "1111";
String s2 = "1111";
- only one object / created in the String pool by 1st stmnt / s2 ref will be SAME as s1 since maximum 1 distinct String object can be in the pool / the 2nd statement WILL NOT create a new String pool obj
case 3:
1. String s1 = "1111";
String s2 = "2222";
String s3 = "11111";
- 2 String objects / created in the String pool ("1111","2222")by 1st and 2nd stmnt / s3 = s1
case 4:
1. String s1 = "1111";
String s2 = "2222";
String s3 = "1111"+"2222";
- 3 String objects / created in the String pool ("1111","2222","11112222")by 1st and 2nd and 3rd stmnts
case 5:
1.final String s1 = "1111";
final String s2 = "2222";
final String s3 = s1 +s2;
- 3 String objects / created in the String pool ("1111","2222","11112222")by 1st and 2nd and 3rd stmnt
case 6:
1. String s1 = "1111";
String s2 = "2222";
String s3 = s1 +s2;
- 2 String objects created in the String pool ("1111","2222")by 1st and 2nd / 1 in heap with content as "11112222" by 3rd stmnt since the individual comp s1 and s2 are not constant valued String objects. S1 and s2 may change it's content if they want in course of their life lifetime unlike final String s1="1111"; which can't change its value.

case 7:
1. String s1 = "1111";
String s2 = "2222";
String s3 = s1 +s2;
- 2 String objects created in the String pool ("1111","2222")by 1st and 2nd / 1 in heap with content as "11112222" by 3rd stmnt.
case 8:
1. String s1 = new String("1111");
- 1 String object created in the heap as a result of this new operation with content as "1111";
- As I asked you to blindly remember the fact that, whenever the Compiler sees a CONSTANT VALUED String object it creates in the String pool. So when the compiler compiles itself it creates a String pool object "1111". At run time the new operation creates ANOTHER HEAP String object whose content is again "1111".
[ YOUR DOUBT TO BE ANSWERED HERE IN THIS CASE 7 ]. As I said before, to assume these are the ONLY statements in a class definition and no other statements, we can be SURE OF there is NO PRE-EXISTING String pool object "1111" for case 7. So this brings down to the total objects created are 2.
If there would have been another code already which comes BEFORE these code in the source program in the order as they are written, then this time new String("1111") will create only 1 heap object right? No String pool object. So if that is a case like the following
String s0 = "1111";
String s1 = new String("1111");
then the 2nd stmnt alone will create ONLY 1 in the heap NOT in POOL since 1st stmnt has ALREADY created one in POOL.
Case 10
String s0 = new String("1111"); // 1 in heap , 1 in pool
String s1 = new String("1111"); // 1 in heap alone (NO POOL)
String s2 = new String("1111"); // 1 in heap alone (NO POOL)
String s3 = new String("1111"); // 1 in heap alone (NO POOL)
String s4 = new String("1111") + new String("2222");
// 1 in heap alone ("11111111") (1 POOL - "2222")
Actually what really happens internally in this case is
- 1 pool object created - "2222";
- 2 heap objects due to 2 new(..) - "1111" ,"2222"
- an intermediate Stringbuffer created in heap
- the 2 heap objs "1111", "2222" are appended to String buffer
- the .toString() of this StringBuffer is called internally, which returns another heap object with content "11112222"

So the in between created objects in heap "1111" and "2222" are eligible for GC
(1) an intermediate String buffer is created in the heap;
(2) 2 String objects created in heap
I tried to explain the concept. But the internals are not needed for the SCJP exam purpose.
regds
maha anna

[This message has been edited by maha anna (edited July 25, 2000).]
 
Surfs up space ponies, I'm making gravy without this lumpy, tiny ad:
Smokeless wood heat with a rocket mass heater
https://woodheat.net
reply
    Bookmark Topic Watch Topic
  • New Topic