加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java多态别别问题

发布时间:2020-12-15 02:48:56 所属栏目:Java 来源:网络整理
导读:如果有3个班级. A,B和C. B类扩展A,C类扩展B. A类有等于方法: public boolean equals(A other){...} B级有等于方法: public boolean equals(B other){...} 和C类有euals方法: public boolean equals(Object other){...} 主要有这些代码行: A a = new A();
如果有3个班级. A,B和C. B类扩展A,C类扩展B.

A类有等于方法:

public boolean equals(A other)
{...}

B级有等于方法:

public boolean equals(B other)
{...}

和C类有euals方法:

public boolean equals(Object other)
{...}

主要有这些代码行:

A a = new A();
C c = new C();
a=c;
System.out.println(a.equals(c));

我无法理解为什么正在执行A类的equals方法.

我知道重载方法是使用静态绑定绑定的.但是指向别名之后的“对象的C部分”并且方法等于C类.为什么不执行C类的equals方法呢?

解决方法

仅当参数具有相同类型时,子类中的方法才会覆盖超类中的方法.

Object类定义了一个equals()方法:

class Object {
    public boolean equals(Object obj) {...}
}

定义类A时,它从Object继承equals例程.您定义了一个新的equals,但参数类型不同,因此它不会覆盖Object中的那个;相反,它变成了一个过载.结果是A有两个重载的equals方法:

class A {
    public boolean equals(Object obj) {...}  // inherited
    public boolean equals(A other) {...}     // the one you wrote
}

类似地,B中的equals不会覆盖equals,所以结果是三次重载equals方法:

class B {
    public boolean equals(Object obj) {...}  // inherited from Object
    public boolean equals(A other) {...}     // inherited from A
    public boolean equals(B other) {...}     // doesn't override anything
}

在C类中,新的equals方法会覆盖Object中的那个,因此仍然有三个equals方法:

class C {
    public boolean equals(Object other) {...}  // overrides the one in Object
    public boolean equals(A other) {...}       // inherited from A
    public boolean equals(B other) {...}       // inherited from B
}

现在,这是你的代码:

A a = new A();
C c = new C();
a=c;
System.out.println(a.equals(c));

当你说a.equals(c)时,编译器会看到a有一个类型A.因此,它会查看A中的方法以查看要执行的方法. (编译器不知道a在运行时会有类型C;因此,它不会查看C中的方法.)

有两种方法可供选择,如上所示:

public boolean equals(Object obj) {...}  // inherited
    public boolean equals(A other) {...}     // the one you wrote

它们都可以用在参数c上,因为c是一个Object而且它是A.在这种情况下,当一个参数是另一个参数的子类时,编译器实质上会选择“最接近的”. C只是远离A的两个子类,它是远离Object的三个子类,因此它选择带参数A的重载,这是你在A中定义的.并注意,这个equals方法从未被覆盖.所以它执行你在A类中编写的代码.

但是假设你写了:

System.out.println(a.equals((Object)c));

通过将c转换为Object,您迫使编译器将其视为Object.现在当它在重载之间进行选择时,它必须选择具有Object参数的那个,因为Object不能自动转换为A(因为并非每个Object都是A).因此,它会选择继承的方法.而且,因为在运行时,对象实际上是C类,并且由于类C有一个等于Object的equals方法,在这种情况下它会执行C语言编写的代码.

您的代码是演示重载和覆盖工作方式的一个很好的示例.但是,在现实生活中,编写一个equals()方法是一个坏主意,该方法的参数不是Object,因为它不会覆盖并且可能导致混淆.此外,将@Override放在您认为会覆盖超类中的方法的任何方法上都是一种很好的做法.这样,如果你使用错误的参数,编译器会在你遇到一个很难追查的运行时错误之前捕获它.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读