• Post Reply Bookmark Topic Watch Topic
  • New Topic

better way of representing an empty string...  RSS feed

 
Vijay Vaddem
Ranch Hand
Posts: 243
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

Just wanted to know if there is any difference between the following
usage of an empty string

1)

String empty = "";

2)

String empty = SomeInterface.emptyString;


Now, in SomeInterface interface...

public static final String emptyString = "";



What happens in my program when i say

String abc = "";
String xyz = "";

compared to .....

String abc = SomeInterface.emptyString;
String xyz = SomeInterface.emptyString;


TIA

Vijay
 
Steven Bell
Ranch Hand
Posts: 1071
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No difference. Strings are interned, so there is only the one object created in either case. (unless you do new String(""); )

Now if you are talking from a readability/architecture standpoint maybe someone could make the case for the static final variable, but I think it would be a real streach. I would find "" more readable as it is something very unlikely to change.
 
David Harkness
Ranch Hand
Posts: 1646
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I got this information from the JVM Class File Specification.

Each .class file maintains its own pool of constants, including String literals. In the first case, both abc and xyz will reference the same String constant in the class that contains them (assuming they are in the same class). In the second case, they will both reference the same String constant in the SomeInterface interface.
 
Steven Bell
Ranch Hand
Posts: 1071
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm fairly certain that the JVM spec requires that all Strings be interned so that any two Strings that are equals() are also == unless one of them was created with the new String("") after that same equals() String existed. If I'm wrong on that I'd be interested to find out. I didn't see on the class spec where it said that each class keeps it's own pool of constant Strings (although I didn't go through the whole thing).
 
Junilu Lacar
Sheriff
Posts: 11476
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Remember guys, this is the beginner JiG. Let's reserve the geeky stuff for JiG-advanced, OK?

Seriously though, I would take a different tack on this for beginners. There is no practical difference. However, considering that Joshua Bloch wrote "The constant interface pattern is a poor use of interfaces" in his book "Effective Java" I would avoid the second form.
 
David Harkness
Ranch Hand
Posts: 1646
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Good point, Junilu. Sometimes I forget to shift gears as I bop around the different forums.

Just one thing, though, since Steven brought it up. I think you're correct, but this is one area I haven't delved into much. I googled briefly for "constant string pool" and the .class specification was all that came up. So what I wrote and that URL only address how the constants defined in a .java file make it into its respective .class file.

Once that class is loaded, I guess it's possible that Java interns the Strings in the class's constant pool.

To be relavent, I'll say that I would definitely not create a constant named EMPTY_STRING any more than I'd create a constant named EIGHT. I would, however, possibly defineTry to name your variables and constants for what they logically represent or how they are used -- not for their values. Values may change, but the logical concept won't. For example, the idea that there is some fixed number of rows won't suddenly change to the idea of the number of days in February, but it may change from 8 to 10.
[ January 29, 2005: Message edited by: David Harkness ]
 
Mike Gershman
Ranch Hand
Posts: 1272
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
First of all, the jvm is free, but not required, to merge the string constant pools as it loads classes.

Second, I find it very hard to believe that a working Java programmer would write code that depends on interned strings being equal under ==.

This might be on the SCJP, but the K&B book does not go into much detail here, so I doubt that as well. Remember the Kathy and Bert helped write the SCJP questions.
 
Mike Gershman
Ranch Hand
Posts: 1272
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ilja Preuss quoted JLS Section 3.10.5. I think it settles the matter:
http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html#19369

There is one constant pool for your entire program at run time. The jvm does merge the class file pools.
 
Jeroen Wenting
Ranch Hand
Posts: 5093
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
you're wrong Steven. It's not required at all to do that.
As an example try the following:


All 3 comparisons will yield false as a result despite them all being between 2 Strings with the value "hello world".
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Mike Gershman:
Second, I find it very hard to believe that a working Java programmer would write code that depends on interned strings being equal under ==.


Unless he had read the official tech tip on the topic: http://java.sun.com/developer/TechTips/1999/tt0114.html#tip3
 
Mike Gershman
Ranch Hand
Posts: 1272
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ilja:

Your link is perfectly clear that using == to compare string literals and interned strings is a good idea, but I do not agree with the recommendation. This would require either that multi-server multi-site applications somehow synchronize their constant pools or that the programmers be be very aware of which classes share a jvm. The latter would in turn make redistributing an application across servers trickier.

What do we gain by writing code that relies on implementation? In most cases, the strings will be different when the first 4 or 8 byte word is compared by equals(). This is not much different from comparing String references, which are not really simple addresses.

Unfortunately for my viewpoint, lots of people are learning this technique early in their Java career, so perhaps they are using it as well. I haven't studied standard Java patterns yet, but I wonder how often they use == with strings.
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Mike Gershman:
This would require either that multi-server multi-site applications somehow synchronize their constant pools or that the programmers be be very aware of which classes share a jvm. The latter would in turn make redistributing an application across servers trickier.


I'm confused - how do you compare strings that are not in the same VM???

What do we gain by writing code that relies on implementation?


What do you mean by "relies on implementation"? It's something that is guaranteed to work by the *specification*, after all.

In most cases, the strings will be different when the first 4 or 8 byte word is compared by equals(). This is not much different from comparing String references, which are not really simple addresses.


In fact, as far as I know String.equals will first compare hashcodes, which is even faster.

But there is still *some* difference, of course.

I wonder how often they use == with strings.


I agree with you that it's not something you do as a daily routine. I don't think I've used that trick once yet, actually.

But I feel good knowing about this trick, so that I can use it should I ever be in the position to need to get the last performance out of string comparisions.

So I think it's something a professional Java programmer should know about, but use wisely.
 
Jeroen Wenting
Ranch Hand
Posts: 5093
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've seen far more places where using == to compare Strings caused problems than places where it was the preferred solution.
In fact I've never yet come across a situation in which using == to compare Strings was anything but a bad solution...
 
Steven Bell
Ranch Hand
Posts: 1071
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jeroen:

If you would have read my post you would have realized I wasn't wrong. Creating a String with the new operator is a special case that I addressed.
 
David Harkness
Ranch Hand
Posts: 1646
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Steven Bell:
I'm fairly certain that the JVM spec requires that all Strings be interned so that any two Strings that are equals() are also ==
It's this part that I don't agree with and snicerely hope is not true. The tech tip specifically states
String literals and string-valued constant expressions are always interned
I infer from this that not all Strings are always intered. If you read a String from a File or over a Socket, will it intern it? If it does do this with every String that gets created, you'll end up with serious performance issues.

As to relying on == when dealing with multi-JVM applications, if you set an object's field to the constant "bob" and then serialize it to send it to another JVM, will "bob" be interned on the other side? If not, your code that depends on "bob" == "bob" will fail whenever checking a locally-instantiated object to a remote-instantiated one. Good luck tracking that intermittent bug down!

I guess I'd save this trick for the last possible performance tweak as Ilja said, but I would certainly not be recommending this on the beginners' forum.
 
Steven Bell
Ranch Hand
Posts: 1071
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm sorry maybe I wasn't clear. I would never recommend relying on the == comparison for Strings. As for Strings over a socket or from a file I have no idea. I was only pointing out that the code in the original post would not benefit from having the static constant String objects.

added the following
P.S. The equals method in the String class does not check the hashCode. It does perform an == check before doing a full comparison, but that is a common 'performance tweak' in the equals method. I'm not sure why it would be faster to check the hashCode before doing a comparison as both involve a traversal over the characters in the String.
[ January 29, 2005: Message edited by: Steven Bell ]
 
David Harkness
Ranch Hand
Posts: 1646
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Steven Bell:
I would never recommend relying on the == comparison for Strings.
Sorry, only the first part of my post was replying to you (I wasn't clear either ). The closest I think anyone came to recommending the use of == was Ilja with
Originally posted by Ilja Preuss
Unless he had read the official tech tip on the topic
which was only pointing out when you can depend on it, not really a recommendation in my book, but seeing as this is the beginners' forum, I wanted to be specific.
Back to Steven's post
The equals method in the String class does not check the hashCode. ... I'm not sure why it would be faster to check the hashCode before doing a comparison as both involve a traversal over the characters in the String.
While it doesn't compare hash codes, it could since it caches the hash code value by inserting this if test:I don't know how often that would help versus hurt, though. If you tend to compare a lot of large unequal Strings that have been put into a hash-based collection at some point, it would pay off. Otherwise it's probably just busy work given that the next comparison is against the length of the two Strings which is faster than comparing the hash codes and probably just as likely to return false for different Strings.
[ January 29, 2005: Message edited by: David Harkness ]
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by David Harkness:
If you read a String from a File or over a Socket, will it intern it?


No. Also not for every other string expression that isn't a compile time constant. You'd need to manually call the intern() method to get it interned.

And I agree that that is an advanced technique - I guess I need to pay more attention to what forum I'm postin in... :roll:
 
Mike Gershman
Ranch Hand
Posts: 1272
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm confused - how do you compare strings that are not in the same VM???

Using most kinds of remote access. For instance, accessor methods using RMI.

You could say that you wouldn't use == under those conditions, but what happens when your small-scale application is really successful and needs to be ramped up big time? Do I have to hunt down every dependency on single-jvm residency?

What do you mean by "relies on implementation"? It's something that is guaranteed to work by the *specification*, after all.


I didn't mean Sun's implementation, I meant not unecessarily relying on the particular hardware/software configuration in your organization. I think that's how we preserve true platform independence.
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Mike Gershman:
Using most kinds of remote access. For instance, accessor methods using RMI.

You could say that you wouldn't use == under those conditions, but what happens when your small-scale application is really successful and needs to be ramped up big time? Do I have to hunt down every dependency on single-jvm residency?


You had to hunt down every such dependency and somehow solve it - either by removing the dependency, or by explicitely interning the string at the boundary.

And you are right, if those dependencies are scattered around in the code, that could become a maintenance nightmare (though I'm not sure that finding all those places by means of static analysis would be that hard).

I still think that, under some circumstances, using interning to remove local performance bottlenecks might be a sensible thing to do.

I didn't mean Sun's implementation, I meant not unecessarily relying on the particular hardware/software configuration in your organization. I think that's how we preserve true platform independence.


Well, if you program in Java, you obviously need to rely on the existence of a JVM. And every JVM needs to conform to the specification, not just those implemented by Sun. It's really not a property of a particular JVM implementation, it's a property of the language in general. I'd therefore say that it's quite safe to rely on it.
 
Vijay Vaddem
Ranch Hand
Posts: 243
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Where are we now ??? :roll:
 
Joel McNary
Bartender
Posts: 1840
Eclipse IDE Java Ruby
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Good question. Where are we now? The answer: Still in the Beginner's forum. I am remeding this, as this is really more intermediate-with-a-dash-of-advanced thrown in.

But basically, the answer to the original question is: Use "" instead of SomeInterface.emptyString, because the constant interface is almost never a good idea.
 
Consider Paul's rocket mass heater.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!