Reputation: 1160
this is equals()
from String
class
public boolean equals(Object anObject)
{
if (this == anObject)
{
return true;
}
else
{
if (anObject instanceof String)
{
String aString = (String) anObject;
if (this.coder() == aString.coder())
{
return this.isLatin1() ? StringLatin1.equals(this.value, aString.value) : StringUTF16.equals(this.value, aString.value);
}
}
return false;
}
}
equals(Object anObject)
but not as equals(String anObject)
?
What's the point of having an opportunity to receive any object if it's return false for any other objects than String
?MyOwnClass
should I override equals()
method asequals(Object obj)
equals(MyOwnClass obj)
P.S.: covariance works in return type when overriding. I thought that if covariance works in return type when overriding so it must work in a function arguments too.
{
public A foo(A o)
{
return new A();
}
}
class B extends A
{
@Override // everything OK
public B foo(A o)
{
return new B();
}
}
Upvotes: 0
Views: 446
Reputation: 103244
No answer so far gets to the heart of the issue.
Java's typing system is covariant (until you get to generics, where you choose which variance you want).
Given that class Apple extends Fruit
and class Fruit extends Object
, then all Apples are also Fruits, all Fruits are also Objects, and all Apples are also Objects.
And Object, because java.lang.Object
says so, has an equals(Object other)
method. That means that apples must also have this method:
equals(Object)
methodequals(Object)
method.So why do objects have this method? Because it's useful. Because it makes ArrayList
's contains(Object other)
method tick, it makes java.util.Set work. Once you've decided that all Objects have an equals(Object other)
method, the rest (specifically, that apples have an equals(Object other)
method, which trivially returns false if you ask it if it is equal to some non-apple object) is locked in; that is now the case simply because the system we've set up here (which is a covariant typing system, where the base type all types inherit from has an equals(Object)
method) dictates it must be so.
Yes, the java language spec in fact guarantees it; you can't 'remove' the equals(Object)
method from Apples. However, the crux of the matter is why the java spec works like this.
Upvotes: 6
Reputation: 140484
What's the point of having an opportunity to receive any object if it's return false for any other objects than String?
Given two Object
s, you can legitimately ask if they are equal, even if the concrete types are, say, Integer
and String
.
Object first = 0; // first is an Integer
Object second = ""; // second is a String
boolean equal = second.equals(first);
The equals
method needs to accept the most general type.
should I override equals() method as
equals(Object obj)
or asequals(MyOwnClass obj)
If as in the first option then why?
The first. If you use the second way, it will only be invoked if both the receiver and parameter are of type MyOwnClass
(as in, receiver.equals(parameter)
). Otherwise, equals(Object)
from Object
will be invoked, because method overloading is resolved by the compiler, and equals(Object)
is the only one the compiler knows that matches receiver and parameter.
Upvotes: 3
Reputation: 79395
So why it is defined as equals(Object anObject) but not as equals(String anObject)?
class String
overrides Object#equals
which has the following signature:
public boolean equals(Object obj)
In the case of overriding, the method signature (name and parameters) in the child class must be the same as in the superclass. If you change the number and/or type of the parameters, the method will be overloaded, not overridden.
If I create MyOwnClass should I override equals() method as equals(Object obj) or as equals(MyOwnClass obj)
You should override it as
public boolean equals(Object obj)
otherwise, it won't be overridden; rather, it will be overloaded as mentioned above.
Upvotes: 3