JComponent uses hardcoded Strings and compares them with "==". Why?

Hi,

I wanted to post to the bugtracking system, but since this is (probably?) not a bug, I'll ask here first. If you look at the source code of JComponent.setUIProperty(String, Object), you'll see sth like this:

void setUIProperty(String propertyName, Object value){

if (propertyName =="opaque"){

if (!getFlag(OPAQUE_SET)){

setOpaque(((Boolean)value).booleanValue());

setFlag(OPAQUE_SET,false);

}

}elseif (propertyName =="autoscrolls"){

if (!getFlag(AUTOSCROLLS_SET)){

setAutoscrolls(((Boolean)value).booleanValue());

setFlag(AUTOSCROLLS_SET,false);

}

}elseif (propertyName =="focusTraversalKeysForward"){

...

...

...

First question: why are those Strings hardcoded in that ugly way, instead of declaring them as (probably package-wide) constants? Moreover, this method isintended to be used by other classes (even if only package-internal), so hardcoding Strings looks like a very bad style... Is this a bug, just programmer sloppiness or are there other reasons?

Second question: Why are Strings compared with == instead of equals()? If the Strings were defined constants, maybe that would have made sense, but combined with hardcoded String it seems almost incredible that this works at all...

A quick test showed me that equal hardcoded Strings are indeed the same according to "==", probably because the compiler optimizes this and uses the same String object everywhere. If this assumption of mine is correct, then this behavior would be highly compiler dependent. Furthermore, it is not clear how and if this works across classes, i.e. if you get a String from another class and compare it with "==" to an equal hardcoded String in your class. Especially if the two classes are compiled with different compilers on different machines, I would be very surprised to see this work...

One final note: above method definition is taken from a J2SE JDK 1.5.0_11. I haven't checked the 6.0 release yet, but it is probably the same there...

Has anyone an explanation for this and/or give me a hint to more info on this topic?

Thanks & greets,

Mike

[2896 byte] By [MikePa] at [2007-11-27 3:41:49]
# 1
Here is some good information that may clear some things up: http://java.sun.com/developer/JDCTechTips/2004/tt0504.html#2
gracklemanna at 2007-7-12 8:45:22 > top of Java-index,Desktop,Core GUI APIs...
# 2

> Here is some good information that may clear some

> things up:

> http://java.sun.com/developer/JDCTechTips/2004/tt0504.html#2

Thanks for that tip! This explains some things...

Still, I wouldn't call the way the Swing developers did things a best practice in such situations - it still relies on the fact that all calls to the above method (and probably many more that nobody knows about) occur with strings as arguments that were at some point in time initialized with String literals. This is probably the case anyway (I personally never use "new String()"), but I still think it would have been much more elegant to use String constants.

And on a side note: this part of String behavior doesn't seem to be promoted very well. In 5 years Java development I haven't seen a word about this anywhere, and I'm probably not an exception... (OK, the JLS says it, but how many Java developers have read the JLS thoroughly?).

Thanks again & greets,

Mike

MikePa at 2007-7-12 8:45:22 > top of Java-index,Desktop,Core GUI APIs...
# 3

> And on a side note: this part of String behavior doesn't

> seem to be promoted very well.

Good thing, too! We're constantly having to tell people NOT to use == to compare strings. I think it was a big mistake to arrange things so that == means value equality sometimes, and identity equality other times. And now, thanks to autoboxing, we have the same potential for subtle, intermittent bugs when we compare integral types.

uncle_alicea at 2007-7-12 8:45:22 > top of Java-index,Desktop,Core GUI APIs...
# 4

> > And on a side note: this part of String behavior

> doesn't

> > seem to be promoted very well.

>

> Good thing, too! We're constantly having to tell

> people NOT to use == to compare strings.

That's not about strings, that's about object comparison in general. It's one of the first things one learns about Java and is covered in the first 30 pages or so of every Java book.

> I think it

> was a big mistake to arrange things so that == means

> value equality sometimes, and identity equality other

> times.

It does always mean identity equality. It's the reuse (aka "internation") of String objects that messes things up. Although I have admittedly also used such "object caches" that I programmed myself in order to be able to use "==" instead of equals(). That's a huge performance boost when these objects are used as keys in heavily queried hash maps.

There's another thing I wanted to note about the code snippet from the OP: The setFlag() in each if block seems to be redundant, since that same flag is queried 2 lines before that and the block is only executed if the flag is cleared. So clearing it again is kind of strange. So same question again, is this:

a) A subtle bug that nobody cared to correct since it does causes only a minimal performance overhead and no wrong behavior

b) Programmer sloppiness

c) Some implementation-internal voodoo that only lives (lived?) in the mind of the class' author

Thanks for any suggestions.

Greets,

Mike

MikePa at 2007-7-12 8:45:22 > top of Java-index,Desktop,Core GUI APIs...