重写—在java中重载equals方法时运行时的行为

368yc8dk  于 2021-06-30  发布在  Java
关注(0)|答案(3)|浏览(272)

这个问题在这里已经有答案了

重写java equals()方法-不工作(8个答案)
19天前关门了。
我有一个学生班,扩展了一个人班。我的超类中没有equals方法,只有图中所示的子类中的两个方法。我试图理解我的第二、第三和第四个print语句的运行时行为。语句1调用接受student参数的equals方法,这很有意义,因为两个被比较的对象都声明为student类型。但是,语句2调用equals方法,该方法接受person参数,而最后两个语句调用object类中的equals方法。有人能解释为什么java是动态类型的,而实际的运行时对象总是一个学生。提前为任何错误道歉!我是新来的,对java也是新来的。我不太关心每个方法的输出,只关心调用哪个方法以及调用原因。

public boolean equals(Student s) {
    System.out.println("inside student equals");
    return true;
}

public boolean equals(Person p) {
    System.out.println("inside person equals");
    return false;
}

public static void main(String[] args) {
    Student s1 = new Student("John", "1", 10, 1.0, 10);
    Student s2 = new Student("John", "1", 10, 1.0, 10);

    Person s3 = new Student("John", "1", 10, 1.0, 10);
    Person s4 = new Student("John", "1", 10, 1.0, 10);

    System.out.println(s1.equals(s2)); // 1
    System.out.println(s1.equals(s3)); // 2

    System.out.println(s3.equals(s4)); // 3
    System.out.println(s3.equals(s1)); // 4
}

输出:

inside student equals
    true
    inside person equals
    false
    false
    false
2guxujil

2guxujil1#

其中person object是调用student的重载equals的参数。这就是为什么你得到打印声明。如果你想把它作为一个学生来比较,那么你需要输入cast。
在对person对象调用equals的情况下,它最终返回一个false,因为person类中没有实现equals。。。然后它默认为对象的实现,即“检查null,然后检查引用是否相同…”。。。否则返回false”。您可以在jdk的源代码中查看实现。

0ejtzxu1

0ejtzxu12#

你犯的最大的错误就是,失踪 @Override 带有 equals 方法。一旦你要做这件事。

@Override
public boolean equals(Object obj) {
    System.out.println("inside person equals");
    return false;
}

@Override
public boolean equals(Object obj) {
    System.out.println("inside student equals");
    return true;
}

一旦您这样做,您的ide将无法编译,迫使您更正应该修改的定义 Object 而不是 Person 或者 Student 类型作为参数。

关于您获得的输出:

在这四个调用中,都没有覆盖 Object#equals 将被调用。
毫无疑问 Student#equals 将在第一次调用中调用,因为两个引用都是 Student 类型。在剩下的三次通话中, Person#equals 将被调用,因为最接近的匹配。
您可以查看此演示以获取说明。

更新

如果你把 equals 内部方法 Student 如这里所示,您应该更容易理解输出。

s1.equals(s2) // 1 -> "inside student equals" will be printed because the param, s2 is of type, Student
s1.equals(s3) // 2 -> "inside person equals" will be printed because the param, s3 is of type, Person

s3.equals(s4) // 3 -> s3 is of type, Person but Person has not overridden equals, therefore Object#equals will be called
s3.equals(s1) // 4 -> s3 is of type, Person but Person has not overridden equals, therefore Object#equals will be called

如果你愿意的话 Student#equals 要在最后两个案例中也被调用,您将需要 s3Student 如下图所示:

System.out.println(((Student) s3).equals(s4)); // 3.1
System.out.println(((Student) s3).equals(s1)); // 4.1
plupiseo

plupiseo3#

根据声明的类型,在编译时确定使用哪个重载方法。
在第二种情况下,您已经声明s3是一个人,因此 equals(Person) 方法。
在第3和第4种情况下,您已经将变量声明为person。person没有equals()方法,因此编译器假定您要使用object中的默认方法:

boolean equals(Object o);

您尚未在任何类中重写该方法,因此默认方法是在运行时使用的方法。

相关问题