【问题标题】:How equals method behaves when overloaded?重载时equals方法的行为如何?
【发布时间】:2019-07-06 15:47:31
【问题描述】:

所以我有下面的测试代码实现

class Employee{
     String name;
     int age;

    @Override
public boolean equals(Object obj) return false;

public boolean equals(Employee obj) return true;     
}

在主要方法中,我有以下代码

public static void main(String[] args) {        
    Object E1 = new Employee();
    Employee E2 = new Employee();

    System.out.println(E1.equals(E2));

}

所以根据我的理解,多态性应该将 E1 与方法 equals(Employee obj) 绑定,因为我传递的是 Employee 类型的对象,而 E1 实例也是 Employee 类型(尽管对 Object 底层实例的引用是 Employee 类型)。 但是,我看到它打印为 false,这意味着 equals(Object obj) 已被调用(已在两个 equals 方法中使用 Sysout 语句进行了验证)。

【问题讨论】:

  • 编译时解析要调用的重载方法,具体取决于参数的声明类型和接收者。由于 E1 的声明类型为 Object,因此唯一可能调用的方法是 equals(Object)(因为 Object 没有任何其他 equals() 方法)。然后多态在运行时调用 Employee 类中的实现而不是 Object 类中的实现。我确定有几十个重复,这就是我没有回答的原因。
  • “行为”是怎样的,它看起来像它工作,直到你在任何实际依赖于合同的地方使用它,然后它就坏了。

标签: java polymorphism overloading


【解决方案1】:

您对绑定方式的理解不正确。

绑定有两个步骤:

  1. 决定调用哪个重载
  2. 决定调用哪个实现。

第一步在编译时完成,基于变量的compile-time类型。第二步在运行时完成,并基于对象的运行时类型。第二步就是你所说的“多态性”。

在第一步中,E1 的编译时间类型是Object,所以只有一个重载equals 可供选择——equals(Object)。因此,选择了该重载。

在第二步中,有两个实现可供选择:

// In Employee class:
public boolean equals(Object obj) return false;

// In Object class
public boolean equals(Object obj) {
    return (this == obj);
}

由于E1运行时类型Employee,正如您正确识别的那样,它选择Employee类中的实现,它总是返回false。

【讨论】:

  • 但是我传递的是 Employee 类型的对象,这不会被考虑吗?就像,在方法覆盖中,它取决于参数的类型
  • @sid 在第一步中,只会考虑编译时类型。 E1 的编译时类型是Object,所以只会找到Object 中声明的方法。您的equals(Employee) 方法在Employee 中声明,因此无法找到。编译器无法“看到”有 equals(Employee) 方法,因为 E1 是编译时类型 Object
  • @sid:不,不会考虑,因为在编译时该信息不可用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-22
  • 1970-01-01
  • 2019-02-02
相关资源
最近更新 更多