简体   繁体   中英

Difference between == and .equals in Java.

I know this has been covered but I've seen inconsistent arguments here on SO.

So if I have:

String a = "apple2e";
String b = "apple2e";

System.out.println("a==b? " + a == b);

I get FALSE .

As I understand it, it's because a and b are two different references to the same object ( apple2e ).

So I would have something like:

a (reference_id 123) ------
                           ---------  "apple2e"
b (reference_id 456) ------

Now, if I just want to compare the contents of the two strings, I would use a.equals(b)

Does that mean that the JVM is simply returning if the two references are pointing to the same object? So it's not really doing a character-by-character comparison?

Thanks

EDIT

Hold the phones. Thanks delnan for pointing out the + precedence!!!

When I change it to:

System.out.println(a == b);

I indeed get true .

This makes more sense.

EDIT 2

I can't believe I didn't catch that. lol

I was doing:

"a==b? " + a == b

Which translates to

"a==b? apple2e" == "apple2e"

No wonder it was false!!

As I understand it, it's because a and b are two different references to the same object (apple2e).

Because of string interning, and only because of string interning a and b are different references to the same String object.


Unfortunately, your code does not do what you think it does. Try this:

String a = "apple2e";
String b = "apple2e";

System.out.println("a==b? " + a == b);    // "false"
System.out.println("a==b? " + (a == b));  // "a==b? true"

Java automatically interns all string literals. That is why the second sysout prints what it does. The first sysout prints only "false" because string concatenation ( + ) has higher precedence than == , so it's equivalent to this:

System.out.println("a==b? apple2e" == "apple2e");

I don't think that's what you meant to test!

This, on the other hand, will give you two separate String instances:

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

System.out.println("a==b? " + (a == b));  // "a==b? false"

Which would schematically look like

a (reference_id 123) ---------------  "apple2e"

b (reference_id 456) ---------------  "apple2e"

and can be reduced to the original situation using String#intern() :

String a = new String("apple2e").intern();
String b = new String("apple2e").intern();

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

eg

a (reference_id 123) ------+
                           +---------  "apple2e"
b (reference_id 456) ------+

Your first example is actually true. The expression in the println just isn't doing what you meant.

String a = "apple2e";
String b = "apple2e";

System.out.println("a==b? " + (a == b));

Will print a==b? true a==b? true note the all important grouping!

You are correct that a and b are two different references to the same object. This is exactly why == returns true when you test it! == tests if two different pointers point to the same location in memory. Both a and b are references to the same place in memory that holds the interned compile time "apple2e" string.

Now if you did this

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

System.out.println("a==b? " + (a == b));

It actually will print a==b? false a==b? false . Because you made two different objects in memory, a and b point to different places.

'a' and 'b' are the same reference, the problem is you are not comparing a and b. You should expect

a==b? false

but you just get

false

This is because + takes precedence over == so what you have is

System.out.println(("a==b? " + a) == b);

In the same way you would expect the following to print true.

System.out.println(1 + 2 == 3);

What you need is

System.out.println("a==b? " + (a == b));

a == b looks to see if the two objects point to the same object in memory. Because they don't, even though their internals are the same, a == b will be false. 1 == 1 will be true though, because integers are primitive variables, while Strings are actually objects.

a.equals(b) is an instance method that internally checks to see if the two strings have the same characters.

If you did:

String a = "hello";
String b = a;

Then a == b would be true.

apple2e is not an object. It is the value pointed by the reference.

String a = "apple2e";
String b = "apple2e";

Here, a , b are objects ( references ) to the value apple2e stored at two different locations.

a and b are two different references to the same object -- PROBABLY

"a==b? " + a

evaluates to the string "a==b? apple2e" which is definitely not the same (either == or equals) as the string "apple2e"

So your code:

System.out.println("a==b? " + a == b);

is just testing if "a==b? apple2e" is the same as "apple2e" which it is not (no matter how you define same).

If you change to the following: System.out.println("a==b? " + (a == b));

You get a==b? true a==b? true

Whats happening here is that a and b both point to an internal cache of Strings that is maintained by the String class.

Here is the implementation of String.equals()

public boolean equals(Object anObject) {
if (this == anObject) {
    return true;
}
if (anObject instanceof String) {
    String anotherString = (String)anObject;
    int n = count;
    if (n == anotherString.count) {
    char v1[] = value;
    char v2[] = anotherString.value;
    int i = offset;
    int j = anotherString.offset;
    while (n-- != 0) {
        if (v1[i++] != v2[j++])
        return false;
    }
    return true;
    }
}
return false;
}

anObject must be a String in order to return true, if it is a reference to the same Object, then it returns true immediately. Otherwise as you can see, is is doing a character by character comparison.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM