I'm a little confused as to what gets called first in the following scenario:
I've got a Person class with a name and an age.
public class Person {
private int age;
private String name;
//constructor, getters, ...
}
I now try to compare two separate Person
objects with the same field values ie same name, same age
System.out.println(person1.equals(person2));
I obviously receive a false
return value because I haven't overloaded the equals(Obj object)
method yet.
But say I don't overload it, I instead write another equals()
method only with a Person
argument:
public equals(Person person) {
return person.get_age()==this.age && person.get_name().equals(this.name);
}
Which method gets called now and why? The line below still returns false
System.out.println(person1.equals(person2));
unless I force person2
to be interpreted as a Person
. The line below therefore returns true
System.out.println(person1.equals((Person)person2));
Here's what's confusing me, I now remove that type cast to Person
and for some reason, when I build and run the code again and again, it keeps coming back true
. The only way to force it to start returning false
again, ie to keep taking the default equals(Object obj)
method again is by deleting the equals(Person person)
method, running the code once, and then pasting back the method I had just deleted. Now the comparison keeps returning false
again.
Is some inbetween state being cached by the JVM? I'm a little new to java in all honesty.
Overriding is when you implement a method that has been declared in a superclass. To qualify as an override, the signature of the override must match (within some tolerance) the signature of the method being overridden.
Overloading is when you have multiple methods with the same name but different signatures.
In the presence of overloads, which one is called is determined solely by the static types of the arguments at the call site . In your example, you have two overloads of equals
:
boolean equals(Object o) { ... }
boolean equals(Person p) { ... }
When you call:
Person p = ...
... equals(p) ...
the overload selection process proceeds as follows:
Here, the argument type is Person
, and both overloads are applicable (since a Person
is an Object
), but equals(Person)
is more specific, so that one is called.
If we changed the story slightly:
Object p = new Person(...);
... equals(p) ...
Now, the static type of p
is Object
, so only the first overload -- equals(Object)
-- is applicable. All we know is that it is an Object
; that it happens to hold a Person
is something that we don't know statically. (We could find it out dynamically with instanceof
.)
To summarize:
Now, you probably don't want to declare equals(Person)
for the same problems you're seeing here -- it looks like an override, but really its an overload, and won't get called when you think it does.
Actually Person
has two methods:
boolean equals(Person);
boolean equals(Object);
(from Object) So obviously person2
is not recognized as Person
. The likely explanation is forgotten (dropped) generic typing.
Person person = new Person();
List<Person> list = new ArrayList(); // Should have been new ArrayList<>();
...
if (person.equals(list.get(0)) { // equals(Object)
With pre-generic typing the compiler no longer checks and falls back on a List of Objects. Maybe your IDE gives a corresponding warning (orange marker).
Tip:
Use getAge
and getName
; camel case in Java. Conventions in java are kept quite strict everywhere.
Do not overload equals
and use @Override
. So much depends on the original equals
, and IDEs are known to warn on personJoop.equals(dog)
that it will always fail.
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.