当前位置: 首页 > 知识库问答 >
问题:

在Java中重载Equals方法时的运行时行为[重复]

董阳平
2023-03-14

我有一个扩展Person类的学生类。我的超级类中没有equals方法,只有我的子类中的两个,如图所示。我正在尝试理解我的第二、第三和第四个print语句的运行时行为。语句1调用了接受学生参数的equals方法,这是有意义的,因为要比较的两个对象都是声明类型的学生。但是,语句2调用了接受人参数的equals方法,而最后两个语句调用了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

共有3个答案

常哲彦
2023-03-14

根据声明的类型,在编译时确定使用哪个重载方法。

在第二种情况下,您已经声明s3是个人,因此使用了equals(Person)方法。

在第3和第4种情况下,您已将变量声明为Person。Person没有equals()方法,因此编译器假设您希望使用来自对象的默认方法:

boolean equals(Object o);

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

万俟宜修
2023-03-14

其中Person对象是调用学生重载的equals的参数。这就是为什么您会得到print语句。如果您希望将其作为学生进行比较,那么您需要对其进行类型转换。

在对Person对象调用equals的情况下,它最终返回一个假as。equals未在Person类中实现。。。然后它默认为对象的实现,即“检查Null,然后检查引用是否相同……否则返回false”。您可以在JDK的源代码中查看实现。

戚晨
2023-03-14

您所犯的最大错误是,使用equals方法缺少@Override注释。一旦你做了,例如。

@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学生类型作为参数的定义。

在这四个调用中,都不会调用被重写的对象equals。

毫无疑问,第一次调用中将调用Student#equals,因为两个引用均为Student类型。在剩下的三个调用中,由于最接近的匹配,将调用Person#equals。

您可以查看此演示以获取插图。

如果如图所示,将两个方法放在学生内部,您应该更容易理解输出。

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

如果您希望在最后两种情况下也调用学生#equals,则需要将s3转换为学生,如下所示:

System.out.println(((Student) s3).equals(s4)); // 3.1
System.out.println(((Student) s3).equals(s1)); // 4.1
 类似资料:
  • 通常,具有固定参数数的方法优于具有可变参数数的重载方法。但是,该示例的行为不同: 输出: main的第三行用一个参数调用该方法,该参数是一个包含两个元素的字符串[]。但这并不是用一个参数执行方法,而是执行varargs方法,就像我给了它两个参数一样(这有点正常,因为它是一个数组)。 现在的问题是:这应该发生吗?我是否发现了错误或未记录的行为?它这样做的原因是什么? 我为什么这么做:我想做一个快捷方

  • 我有以下代码片段: 如果我调用foo(null)为什么没有歧义?为什么程序调用foo(字符串x)而不是foo(对象x)?

  • 问题内容: 考虑以下Java代码: 第一个打印语句打印,第二个打印语句。 如果这是故意的行为,这将如何帮助Java编程? 如果这不是故意行为,那么这是否是Java中的缺陷? 问题答案: 我将保留您的问题,但您应该知道,如果该问题的目的是让您学习并且您的解决方案是询问StackOverflow,那么您会很受伤。那边… 此行为是故意的。 默认方法on 比较 内存地址 ,这意味着所有对象都互不相同(仅对

  • 本文向大家介绍java中重写equals()方法的同时要重写hashcode()方法(详解),包括了java中重写equals()方法的同时要重写hashcode()方法(详解)的使用技巧和注意事项,需要的朋友参考一下 object对象中的 public boolean equals(Object obj),对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 tr

  • 本文向大家介绍java中为何重写equals时必须重写hashCode方法详解,包括了java中为何重写equals时必须重写hashCode方法详解的使用技巧和注意事项,需要的朋友参考一下 前言 大家都知道,equals和hashcode是java.lang.Object类的两个重要的方法,在实际应用中常常需要重写这两个方法,但至于为什么重写这两个方法很多人都搞不明白。 在上一篇博文Java中e

  • 本文向大家介绍为什么在重写 equals方法的同时必须重写 hashcode方法,包括了为什么在重写 equals方法的同时必须重写 hashcode方法的使用技巧和注意事项,需要的朋友参考一下 我们都知道Java语言是完全面向对象的,在java中,所有的对象都是继承于Object类。 其 equals 方法比较的是两个对象的引用指向的地址,hashcode 是一个本地方法,返回的是对象地址值。O