It's not a secret anymore!*
The moose likes Beginning Java and the fly likes String class issue in JSP Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "String class issue in JSP" Watch "String class issue in JSP" New topic
Author

String class issue in JSP

Kim Ming Yap
Ranch Hand

Joined: Dec 17, 2008
Posts: 53

I have encountered something weird while using JSP as shown below on the code.

=======================================================================================================

function gotoCS(url, accessMF){

<%System.out.println(companyID);%>
<%System.out.println(companyID.hashCode());
System.out.println("CGI".hashCode());%>
<%System.out.println(companyID == "CGI");%>

=======================================================================================================

output:

CGI
66661
66661
false

=======================================================================================================

So variable companyID is CGI and its confirm hashcode is 66661. The literal "CGI" of course also produce the same hashcode integer.
Though this is not used in any hashtable .. from my understanding of the String class, both should be pointing to the same memory location.
Why is it then returning false?

Please advice.
Thanks.

Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

Those are all basic Java questions which have nothing to do with the fact that you chose to put that code in a JSP scriptlet. So let me move this to a more suitable forum.

As for JSP scriptlets, they have been superseded for 7 or 8 years now. If you're just starting with JSP, don't start with scriptlets.
Bear Bibeault
Author and ninkuma
Marshal

Joined: Jan 10, 2002
Posts: 60782
    
  65

This has nothing to do with JSP. You compare Strings with equals(), not ==.


[Asking smart questions] [Bear's FrontMan] [About Bear] [Books by Bear]
Bear Bibeault
Author and ninkuma
Marshal

Joined: Jan 10, 2002
Posts: 60782
    
  65

Paul Clapham wrote:As for JSP scriptlets, they have been superseded for 7 or 8 years now.
9, actually!
Kim Ming Yap
Ranch Hand

Joined: Dec 17, 2008
Posts: 53

Thanks for all your reply.
The reason i put it here is because:

1. If you do the following example:

String x = "abc";
System.out.println(x == "abc");

This will always return true. String class will always use the intern object.

So why is it behaving like this in JSP?
Ralph Cook
Ranch Hand

Joined: May 29, 2005
Posts: 479
I don't think you've answered his question, which was why == returns false in this example.

We don't have the code for the creation of the variable that holds the value. If you had created it with

companyID = "CGI";

then I think the == would return true. But if you read "CGI" out of database, or concatenated its three letters, or had the user input it, then I wouldn't expect it to. The poster who said you are supposed to use .equals() to compare strings is mostly correct, though there are situations where you really are trying to determine whether two variables refer to the same object. But you can't guarantee that about Strings unless you use something like the String.intern().

I don't know for a fact that they're guaranteed even if you use x = "string"; though I understand most implementations work that way. But if you want to guarantee it, you have to do something different.

rc
Kim Ming Yap
Ranch Hand

Joined: Dec 17, 2008
Posts: 53

Thanks for your reply.

The companyID is from here:

companyID = (String) session.getAttribute("UserLDAPOrg");

This is the only place it get is value from.

The reason i am not using .equals is i don't need to.

A string literal like "CGI" is a reference to a string object.
I expect this reference to be the same as companyID.

Why is it not using the intern object?

So why returning false?

However as i mention earlier if you code the simple one from my earlier email .. it always return true!
Ralph Cook
Ranch Hand

Joined: May 29, 2005
Posts: 479
Well, I've actually already told you.

You can "expect" those to be the same all you want. But they are not guaranteed to be the same in Java, period.

They are often the same based on implementation, so if you write little test programs to see if they're the same, then sometimes they will be. Whether they are in these cases will depend on all sorts of things, most of which you don't want to know about.

You may think you don't need to use equals(), and I guess you don't unless you want to know whether the two String variables have the same value. You CANNOT depend on them referring to the same object.

If you need them to be the same, use the String function intern(); that will force the string variable to refer to the String from a pool if it's there, and create it if it is not. Any String variable assigned using .intern() will refer to the same string if the case-sensitive string is the same as any other variable assigned that way. It sounds like the functionality you are looking for. It isn't using the intern object now because you haven't told it to. Many of us assigning string variables in OUR programs do not WANT java to ALWAYS look up the intern variable, so it doesn't do it always.

rc
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4167
    
  21

Kim Ming Yap wrote:Thanks for your reply.

The companyID is from here:

companyID = (String) session.getAttribute("UserLDAPOrg");

This is the only place it get is value from.

That isn't totally true. The value got put into the session somehow. Chances are it was read in from a database or a config file, or 'created' rather than entered in code as a String Literal. Test this:

What do you get (assuming that is compilable... sorry didn't run it)?

The reason i am not using .equals is i don't need to.

Incorrect. You do need to use .equals() for ANY object that you want to test for equality (rather than identity). This avoids the problem. The assumption you are making is that ALL Strings get put in the String pool, and there fore if 2 Strings have the same content they will use the same object. This isn't true. Only String literals are automatically added to the String pool (and ones you intern() as mentioned earlier I think). Since the companyID was not created from a String literal, then it can not be assumed to be in the String pool.

A string literal like "CGI" is a reference to a string object.
I expect this reference to be the same as companyID.

Why is it not using the intern object?

So why returning false?

However as i mention earlier if you code the simple one from my earlier email .. it always return true!


Steve
Ashutosh M Kulkarni
Ranch Hand

Joined: Jun 07, 2010
Posts: 41

Please have a look at the figure and read the explanation.


The reason you don't see what you expect is because String objects are immutable. That is, once you create a String object, you can not EDIT it. You can only operate on it to create NEW String objects as output.
For example, when you use split() method on a String, it returns an array of String objects, which are actually new String objects, keeping the original String object as it is.In your case, when you create your variable with above code, you are creating a String object with value "CGI" and assigning the reference variable companyID to that object. (See the first assignment in figure).When you try to compare, (experts, please correct me if I am wrong here), the companyID == "CGI" part creates a new String object, not referenced by any object; because a new reference variable wasn't created pointing to that object. At this point, you have TWO String objects both with value "CGI". One is being pointed to by ref variable companyID. The second "CGI" object is shown in figure not pointed to by any reference variable.

Your comparison will always return false because with the == operator, you are just trying to check if the objects being pointed to are the same. And they are NOT same (as seen in the figure).
As for equals() method, it checks whether the objects are meaningfully equal, i.e. their content, not just references.

Steve Luke wrote:Test this:

What do you get (assuming that is compilable... sorry didn't run it)?


As per my knowledge, this will always return false, as there are two objects getting created with value "abc" and == is again checking for references, not actual content.

Hope this helps,
Ashutosh.


SCJP 6, next stop - OCPJWCD!
Ralph Cook
Ranch Hand

Joined: May 29, 2005
Posts: 479

When you try to compare, (experts, please correct me if I am wrong here), the companyID == "CGI" part creates a new String object, not referenced by any object; because a new reference variable wasn't created pointing to that object. At this point, you have TWO String objects both with value "CGI". One is being pointed to by ref variable companyID. The second "CGI" object is shown in figure not pointed to by any reference variable.


From http://java.sun.com/docs/books/jvms/second_edition/html/ConstantPool.doc.html :

In addition, certain nonreference runtime values are derived from items found in the constant_pool table:

* A string literal (§2.3) is derived from a CONSTANT_String_info structure (§4.4.3) in the binary representation of a class or interface. The CONSTANT_String_info structure gives the sequence of Unicode characters constituting the string literal.

* The Java programming language requires that identical string literals (that is, literals that contain the same sequence of characters) must refer to the same instance of class String. In addition, if the method String.intern is called on any string, the result is a reference to the same class instance that would be returned if that string appeared as a literal. Thus,

("a" + "b" + "c").intern() == "abc"

must have the value true.

* To derive a string literal, the Java virtual machine examines the sequence of characters given by the CONSTANT_String_info structure.

o If the method String.intern has previously been called on an instance of class String containing a sequence of Unicode characters identical to that given by the CONSTANT_String_info structure, then the result of string literal derivation is a reference to that same instance of class String.

o Otherwise, a new instance of class String is created containing the sequence of Unicode characters given by the CONSTANT_String_info structure; that class instance is the result of string literal derivation. Finally, the intern method of the new String instance is invoked.



So string literals of the same value are all going to point to the same object. If you use intern(), any string of the same value as a literal or of any other string reference created with intern() will point to the same object. It is not true that a literal in an equals expression necessarily causes creation of an additional, unreferenced object.

rc
Ashutosh M Kulkarni
Ranch Hand

Joined: Jun 07, 2010
Posts: 41

Ralph Cook wrote:It is not true that a literal in an equals expression necessarily causes creation of an additional, unreferenced object.

Sure there must be some or other exceptions to my explanation. I learned a great deal about intern() method from this thread as I was unaware about these facts.

Although, my explanation was subject to the first thread and not to the discussion about intern() method.
When intern() is not used, by default, String objects pool more or less work as explained in my post. Though, not exactly.
According to this post, a String literal created without using the new keyword is reused on similar usage in future, i.e. This will always print the output:
true
true

Here, the reference variable one and two, both point to the same String literal.

@Kim Ming Yap,
You should look more into the explanation of immutability of String objects. It's wonderful how Strings are managed in the String literals pool.


Regards,
Ashutosh.
Ralph Cook
Ranch Hand

Joined: May 29, 2005
Posts: 479
Ashutosh M Kulkarni wrote:
When intern() is not used, by default, String objects pool more or less work as explained in my post. Though, not exactly.

No, "String objects pool" does not work anything like you explained in your post.
You gave two lines of code:

and then said
the companyID == "CGI" part creates a new String object, not referenced by any object...

and
Your comparison will always return false...


This is just wrong, according to the definition of the Java language which I quoted above. This particular fact is not altered by the definition or use of intern(), and I don't think is covered by "Though, not exactly".

None of this has much to do with immutability, either.

rc
samir vasani
Ranch Hand

Joined: Nov 24, 2010
Posts: 59
Ralph Cook wrote:
Ashutosh M Kulkarni wrote:
When intern() is not used, by default, String objects pool more or less work as explained in my post. Though, not exactly.

No, "String objects pool" does not work anything like you explained in your post.
You gave two lines of code:

and then said
the companyID == "CGI" part creates a new String object, not referenced by any object...

and
Your comparison will always return false...


This is just wrong, according to the definition of the Java language which I quoted above. This particular fact is not altered by the definition or use of intern(), and I don't think is covered by "Though, not exactly".

None of this has much to do with immutability, either.

rc

Dear Ralph ,

You have given a tremandous explanation about String.About its immutability,intern().
I never thought this much abt intern() and that you gave an example.
Ashutosh M Kulkarni
Ranch Hand

Joined: Jun 07, 2010
Posts: 41

@Ralph,
I am not here to prove anyone wrong or anything. While carefully quoting pieces of my post, you probably missed one little "Experts, please correct me if I am wrong" part...
Although, you did correct me and gave the right explanation of what I had incorrectly put.
So, thanks.

NOM.
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: String class issue in JSP
 
Similar Threads
Comparing Maps hashcodes problem??
custom tag help
String equvalence....
doubt in hashcode...
can you please this doubt about hashcode()