问题
The reason behind asking the question is that String in Java are interned So
String s1 = "Hello";
String s2 = "Hello";
Both s1 and s2 will point to same object in the memory. Two different objects will not be created.
s1.equals(s2)
should return true and it does.
Now In java documentation it says that String class overrides the equals method of object class. But does it really?
Because even if the String class does not override the Object.equals()
, even then the output of the equals method would remain the same.
If it does override, why is it needed?
回答1:
Not all "String in Java are interned". Try reading something from a file or console, those Strings aren't "interned", thus equals()
(and also hashcode()) needs to be overriden.
回答2:
String
overrides equals
. Simple test,
String a = "a";
String b = new String("a");
System.out.println(a == b); // <-- false
System.out.println(a.equals(b)); // <-- true
QED.
回答3:
I recommend Elliott's example as simple and incontrovertible proof.
Here two more pieces of evidence the String
overrides the Object.equals(Object)
The javadoc implies so. Notice that equality is based on the contents of the string. Indeed, even the existence of a distinct javadoc for the
String.equals(Object)
method implies that the method has been overloaded ... given the way that javadocs are generated.The source code says so. Clearly the linked code is an overload. And clearly it is not simply comparing object references.
Your reasoning has a flaw in it. You have assumed that any two strings with the same sequence of characters will be represented by the same object. This is incorrect in general. The only case where this is always true is if the two strings were obtained from string literals in your source code.
It is only string literals that are automatically interned. Other strings are only interned when you produce them by calling String.intern()
.
回答4:
String does override equals(), as seen in the extract from the source code below. Click here for source code.
However, it doesn't mean it uses this equals code all of the time. As you might know, Java starts out by interpreting the code from bytecode to machine code, and only after some time JIT compiles it into machine code. Now, at the stage of interpreting, the java.lang.String#equals method is used to compare strings. However, it's very slow. That's why, when JIT compiles the code, compiled code uses a different version of equals(), that is much faster (and not written in Java, I assume). Unfortunately, can't give you any details on this, so you'd have to dig into it yourself.
Coming back to your question, why override equals()?
- You can initialize a string as a literal, like the code you provided (String s = ".."). In this case, all strings are interned from the get-go. Quote from javadoc:
- All literal strings and string-valued constant expressions are interned. String literals are defined in section 3.10.5 of the The Java Language Specification
So you can compare them by references, using ==. And it'll work just fine! But imagine you initialize String like objects:
String s1 = new String("some string");
String s2 = new String("some string");
If you compare these two strings by ==, then the result would be false. That's because object strings are not interned by default. You'd have to manually do it by using .intern() on them, and then compare them by reference. Or, if you don't want to do it, that's where equals() comes in. Should you do s1.equals(s2) on object strings (not interned), the result would be true.
- However, interned strings are a bit of an evil thing. String pool has limited size, it cannot grow any further. And by the time you run your main() method, it already has a bunch of strings in it. So it's used by the system. Now, if you intern every single string you come across to then compare them by reference ("=="), can you image what would happen? :) String pool would simply run out of space, and that's baad.
If you want to know more about java.lang.String, I highly recommend you watch Alexey Shipilev. The link to the video presentation. He pretty much confirms everything I've written above.
回答5:
If you have String x = new String("a")
and String y = new String("a");
then x
and y
refer to two different objects. x == y
will be false in this case. The default implementation of equals
method as provided by Object.java
considers ==
as it could not decide the logical equality parameters for the subclasses. As the logical values for both objects referred by x
and y
are same hence equals
is overridden and return true
for such cases also.
While learning we often get numerous such questions, our best mentors are the **javadocs, jdk source code ( yes java code is open and you can read it), try it yourself (for this you could have tried creating String Objects by different ways and then tried invoking .equals
) , debug
来源:https://stackoverflow.com/questions/43255360/what-is-the-need-to-override-equals-method-in-string-class