Reputation: 11420
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!!
Upvotes: 4
Views: 7684
Reputation: 360026
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"
e.g.
a (reference_id 123) ------+
+--------- "apple2e"
b (reference_id 456) ------+
Upvotes: 7
Reputation: 8534
If you change to the following:
System.out.println("a==b? " + (a == b));
You get
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.
Upvotes: 1
Reputation: 533870
'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));
Upvotes: 5
Reputation: 47994
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
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
. Because you made two different objects in memory, a and b point to different places.
Upvotes: 6
Reputation: 10891
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).
Upvotes: 1
Reputation: 11647
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.
Upvotes: 4
Reputation: 34655
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.
Upvotes: 1