String comparison using equals() and ==

C

Chanchal

Hello All,

Forgive my ignorance.

I always thought that we should not use == for comparing two different
String objects because == will compare the references and will never
return true even when the value of the compared Strings are the same

Today a colleague of mine showed that I was wrong. Was I always wrong
or recent versions of java included this feature?

Regards

Chanchal
 
R

RedGrittyBrick

Chanchal said:
Hello All,

Forgive my ignorance.

I always thought that we should not use == for comparing two different
String objects because == will compare the references and will never
return true even when the value of the compared Strings are the same

public class Equality {
public static void main(String[] args) {
String a = "foo";
String b = a;
System.out.printf("%s:%s==%s\n",a,b,a==b?"same":different");
String c = new String(a);
System.out.printf("%s:%s==%s\n",a,c,a==c?"same":"different");
}
}

foo:foo==same
foo:foo==different

Today a colleague of mine showed that I was wrong. Was I always wrong
or recent versions of java included this feature?

I expect you are both wrong.

Note that a="foo";b="foo" would assign the same ref to a and b because
the compiler cleverly combines the two "foo" into a single string reference.

You should not use == for comparing string values.
 
Q

Qu0ll

Chanchal said:
Hello All,

Forgive my ignorance.

I always thought that we should not use == for comparing two different
String objects because == will compare the references and will never
return true even when the value of the compared Strings are the same

Today a colleague of mine showed that I was wrong. Was I always wrong
or recent versions of java included this feature?

Using == will compare the references to the strings and is rarely of any use
in general programming. Using equals() will compare the contents of the
strings and is almost always what is needed in practice.

--
And loving it,

-Qu0ll (Rare, not extinct)
_________________________________________________
(e-mail address removed)
[Replace the "SixFour" with numbers to email me]
 
R

Roedy Green

I always thought that we should not use == for comparing two different
String objects because == will compare the references and will never
return true even when the value of the compared Strings are the same

Today a colleague of mine showed that I was wrong. Was I always wrong
or recent versions of java included this feature?

If the Strings are interned, then you can use ==. Otherwise you must
use .equal

http://mindprod.com/jgloss/string.html#COMPARISON
http://mindprod.com/jgloss/interned.html
 
M

Mayeul

Chanchal said:
Hello All,

Forgive my ignorance.

I always thought that we should not use == for comparing two different
String objects because == will compare the references and will never
return true even when the value of the compared Strings are the same

Today a colleague of mine showed that I was wrong. Was I always wrong
or recent versions of java included this feature?

I'm wondering what your colleague actually showed.
 
M

Mike Amling

Thomas said:
public class Foo {

public static void main(String[] args)
{
int v = Integer.parseInt(args[0]);
String z = Integer.toString(v);
System.out.println(System.identityHashCode(z.intern()));
z = null;
System.gc();
z = Integer.toString(v);
System.out.println(System.identityHashCode(z.intern()));
}
}

(To launch with "java Foo 42" or any other integer argument.)

With my machine (Sun's JVM 1.6.0_14, Linux, amd64), this prints out
two distinct integers, which means that the two calls to intern()
did not return a reference to the same String instance, even though
they operated on strings with identical contents.

That's actually reassuring. By not permanently caching, intern
reduces the amount of storage it uses.
The effect of including
System.out.println(System.identityHashCode("42");
at some point in your program is interesting. I would have thought the
literal would be interned before its first use, but it isn't.

Of course I presume you do not claim to have a program of the
following form that prints "true"
String x, y;
...
System.out.println(x.equals(y) && x.intern()!=y.intern());

--Mike Amling
 
R

Roedy Green

But it may also return true if the references happen to
be the same.

Even stronger, == will ALWAYS return true if the references point to
the same object.
 
R

Roedy Green

public static void main(String[] args)
{
int v = Integer.parseInt(args[0]);
String z = Integer.toString(v);
System.out.println(System.identityHashCode(z.intern()));
z = null;
System.gc();
z = Integer.toString(v);
System.out.println(System.identityHashCode(z.intern()));
}

However, even with this behaviour, intern still works for all
practical purposes. When you compare two interned strings containing
the same characters with == they still ALWAYS come out true.

see http://mindprod.com/jgloss/interned.html#GC
 
D

Daniel Pitts

Christian said:
The more recent the Java version is the better the Compiler becomes in
automatically interning Strings. So actually it will very often happen
that == will return true if both Strings were not somehow read over IO
or sth else...
wrapping new String(); around some given string alone won't guarantee
to generate a new String for example but actually a reference to the
same string
I beg to differ. Can you provide reference and/or SSCCE to demonstrate
this flagrant disregard for the JLS.
so
String a = "hello";
String b = "hello";
String b2 = new String("hello");
String b3 = new String(a);
String b4 = (Math.random() < 1.0f? "h":"")+"ello";

a == b will definately be true
though a == b2 should also be true I doubt that strongly.
so is a == b3 Again, I doubt it.
amazingly a == b4 also returned true here in a test
Hmm, don't think so.
<sscce>
public class Strings {
public static void main(String[] args) {
String a = "hello";
String b = "hello";
String b2 = new String("hello");
String b3 = new String(a);
String b4 = (Math.random() < 1.0f ? "h" : "") + "ello";
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("b2 = " + b2);
System.out.println("b3 = " + b3);
System.out.println("b4 = " + b4);
System.out.println("a==b = " + (a==b));
System.out.println("a==b2 = " + (a==b2));
System.out.println("a==b3 = " + (a==b3));
System.out.println("a==b4 = " + (a==b4));
}
}
</sscce>
<output>
a = hello
b = hello
b2 = hello
b3 = hello
b4 = hello
a==b = true
a==b2 = false
a==b3 = false
a==b4 = false
So my recommendation is use equals for String comparison but be aware
that many more string objects might be the same and comparable with ==
which should mean for you: never use Strings as Monitor for synchronization.
Unless you explicitly intern them.
Even so, there are often better approaches.
 
K

Kevin McMurtrie

Christian said:
The more recent the Java version is the better the Compiler becomes in
automatically interning Strings. So actually it will very often happen
that == will return true if both Strings were not somehow read over IO
or sth else...
wrapping new String(); around some given string alone won't guarantee
to generate a new String for example but actually a reference to the
same string

so
String a = "hello";
String b = "hello";
String b2 = new String("hello");
String b3 = new String(a);
String b4 = (Math.random() < 1.0f? "h":"")+"ello";

a == b will definately be true
though a == b2 should also be true
so is a == b3
amazingly a == b4 also returned true here in a test


So my recommendation is use equals for String comparison but be aware
that many more string objects might be the same and comparable with ==
which should mean for you: never use Strings as Monitor for synchronization.

Christian

Constructors should never be optimized away. It's rare to use the
String constructor that takes a String argument but it has a couple of
uses.

Side topic: If you need to access a Properties map very frequently,
rebuild it with String.intern() on the keys. That enables a much faster
code path when looking up values with a hard-coded key name.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top