• 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
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

String class issue in JSP

 
Ranch Hand
Posts: 53
Android C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.

 
Marshal
Posts: 28177
95
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Sheriff
Posts: 67746
173
Mac Mac OS X IntelliJ IDE jQuery TypeScript Java iOS
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This has nothing to do with JSP. You compare Strings with equals(), not ==.
 
Bear Bibeault
Sheriff
Posts: 67746
173
Mac Mac OS X IntelliJ IDE jQuery TypeScript Java iOS
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paul Clapham wrote:As for JSP scriptlets, they have been superseded for 7 or 8 years now.

9, actually!
 
Kim Ming Yap
Ranch Hand
Posts: 53
Android C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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?
 
Ranch Hand
Posts: 479
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 53
Android C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 479
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Bartender
Posts: 4179
22
IntelliJ IDE Python Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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!

 
Ranch Hand
Posts: 41
Eclipse IDE Firefox Browser Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Ralph Cook
Ranch Hand
Posts: 479
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


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
Posts: 41
Eclipse IDE Firefox Browser Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 479
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
 
Ranch Hand
Posts: 65
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 41
Eclipse IDE Firefox Browser Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
@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.
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic