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.
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).
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.
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.
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) ------+
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.
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.