3

Possible Duplicate:
String equality vs equality of location

I just got my first assessed coursework back with a mark of 97.14%, and the comment "When comparing strings you need to use the .equals() method of String == does not work the way you might expect."

How is == on Strings different, and if this is the case then why did my tests all work correctly anyway?

Community
  • 1
  • 1
Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592

8 Answers8

14

You got lucky. "==" compares the two objects to see what memory address they reference. It has nothing to do with what's actually in the string.

As pointed out in the comment below, if you're comparing two string constants, they may (will?) end up in the same memory location. So

String a = "abc";
String b = "abc";

In that case, (a == b) will return true. However if you force them into different memory locations with

String a = new String("abc");
String b = new String("abc");

then (a == b) will not return true.

Paul Tomblin
  • 179,021
  • 58
  • 319
  • 408
  • 6
    As a note: The current javac currently interns strings so that: `"foo" == "foo"` is always true. (It might be part of the JLS, I don't know.) However, as Paul pointed out, that's because there is really only one "foo" string in the above example, and an object is always "==" itself. On the other hand, this will never be true: `new String("foo") == "foo"`. So -- Java 101: You always want `equals` to compare non-primitive object values. And `==` to check for *object identity*. (I'd argue 42 == 42 is checking identity as well...) –  Nov 23 '10 at 19:05
  • 3
    @pst: Yes, this is guaranteed as part of JLS. – Jon Skeet Nov 23 '10 at 19:07
  • 1
    Second sentence is incorrect. The == operator does not compare two objects. Its operands are references to objects, and == checks that the references are equal -- that they point to the same object. – Andy Thomas Nov 23 '10 at 19:24
5

Basically, == compares to see if your two variables are the same object. For most string comparisons, this will only work by coincidence. The .equals() function will check the contents of your two string objects and tell if you if they are the same.

The root of it that there are two kinds of equality: reference and value.

Read all about it here (among many others, I'm sure): http://leepoint.net/notes-java/data/expressions/22compareobjects.html

FrustratedWithFormsDesigner
  • 26,726
  • 31
  • 139
  • 202
2

The == operator if Java compares by reference, not by value. More correctly, it compares two string references by value, but does not compare the referenced objects by content.

See this article for more reading.

cdhowie
  • 158,093
  • 24
  • 286
  • 300
1
class test{
public static void main(String[] args)
{
String a =new String("ABC");
String b =new String("ABC");
System.out.println(a==b); //prints False
System.out.println(a.equals(b)); //prints true
}
}
Sekhar
  • 5,614
  • 9
  • 38
  • 44
  • 1
    Note the `new String()` here, if you don't do this you will hit the string cache, which creates only one object for each literal. – Ivo Wetzel Nov 23 '10 at 19:10
  • Yeah - I know that. I wanted to show the case where two seemingly equal strings would fail the == test. – Sekhar Nov 23 '10 at 21:01
1

In Java, there are two different types: primitives and object references.

Primitives include integers, floats etc and == works as you expected. With object references, when you use ==, it tests whether the references are equal, not whether the objects which those references point to are equal.

String is not a primitive, it is an object; therefore == will test the reference equality. You need to test equals() method to test for equality in terms of object's values.

As you can see, Java is not a pure object oriented language in this sense, you have variables that are not objects. For example, since integers are primitives, they don't have methods, so you can't do things like 3.add(4). Sometimes though, you need to make an object out of integers, that is when the wrapper classes like Integer come in. The conversion is automatic in some cases, and this is called autoboxing. For example, when you put an int to an ArrayList, autoboxing converts the int to an object since ArrayList accepts only objects; this conversion had to be manually done before Java 5.

ustun
  • 6,941
  • 5
  • 44
  • 57
1

It is relevant not only for strings but for all objects. Operator == compares references while equals() method should compare the object content. References are equal for the same object only.

BTW it is relevant for other languages also. Reference in java is like pointer in C. So, the same comparison rule is relevant for C also.

You are lucky that you got 97. I'd put you 25. Maximum 27. :)

AlexR
  • 114,158
  • 16
  • 130
  • 208
0

== compares object references so will return true if the two objects refer to the same actual memory location.

equals(Object) by default (in the Object class) just calls == but is generally overridden to test whether two objects have the same content.

For the String class, there's an extra wrinkle because the compiler (and possibly the JVM too) will generally try to ensure that two String references that are assigned the same literal string value refer to the same String object.

So:

String a = "xxx";
String b = "xxx";

System.out.println(a == b);  // usually "true"

The above code usually prints "true" because the compiler only stores one "xxx" literal and a and b both refer to it. This may even be true if a and b are defined in completely separate classes but I'm guessing now.

Adrian Pronk
  • 13,486
  • 7
  • 36
  • 60
  • "ensure that two String objects that are assigned to the same literal string" -- should be "two String *references*. – Andy Thomas Nov 23 '10 at 19:26
0

Here is the best way to explain the difference:

String a = new String("foo");
String b = new String("foo");

if(a == b) {
  // Does not execute
}

if(a.equals(b)) {
  // Executes
}

// Now make a reference the same memory location as b
a = b;

if(a == b && a.equals(b)) {
  // Executes
}

Since this is your first assignment, it doesn't surprise me that you didn't get this right. A lot of people get tripped up on this when they're first learning to code. Try thinking about it this way...

"==" is true when comparing the EXACT same thing. Imagine that your father's name is Bob. When you call him "father" or someone else calls him "Bob", you're both referring to the same person. This is what "==" is used for [So Bob == father].

".equals" is true when you're comparing similar objects. So, if you just bought a 2008 Honda Accord and your friend just bought a 2008 Honda Accord, you would say you both have the SAME car. Even though, they are not the EXACT same car [So yourCar.equals(yourFriendsCar)]. This varies a lot though, because it is the programmer who gets to decide what makes two objects the same.

Dave
  • 6,141
  • 2
  • 38
  • 65