Java继承和重写方法——修饰符的影响

标签 java inheritance overriding modifiers

我遇到以下四个类的问题:

class X {
    void a() {
        b();
        c();
    }
    void b() {
        System.out.println("b from class X");
    }
    private void c() {
        System.out.println("c from class X");
    }
}

class Y extends X {    
    void b() {
        System.out.println("b from class Y");
    }
}

class Z extends Y {    
    void b() {
        System.out.println("b from class Z");
    }
    void c() {
        System.out.println("c from class Z");
    }    
}


public class Main {

    public static void main(String[] args) {
        Y y = new Z();
        y.a();
    }

}

请不要评论类(class)的合理性,这只是一个例子。我还尝试通过使用 Eclipse 调试器的方法来跟踪 JVM 的流程,但这些方法的步骤在某些时候有点快。

我已经知道了

Y y = new Z();

创建 Z 类的新实例并将其分配给 Y 类的引用。由于Z中没有构造函数,编译器会在每个父类(super class)中查找是否有构造函数,如果没有,则使用对象类的构造函数。 之后

y.a();

方法被调用。类 Z 中没有这样的方法,因此我们再次到达存在方法 a 的类 X 并执行它。 首先我们执行方法b,因为你的对象是类Z的实例,并且方法b在类Z中被覆盖,导致输出

b from class Z.

之后调用方法c(在方法a中)。由于我们的实例仍然是类 Z 的实例,并且该类中存在方法 c,因此您可能会想到输出

c from class Z

将会发生。但这不是真的,因为类 X 中的 c 方法是私有(private)方法。由于它是私有(private)的,因此不能继承到子类(甚至看不到)。因此,任何从 X 继承的类都不需要具有 c 方法。是不是因为从方法 a 调用 c 导致调用类 X 中的 c 方法而不是类 Z 中的 c 方法?

所以回顾一下: 我上面的解释正确还是我遗漏了什么?我只是有点困惑,虽然我的实例来自类 Z,但从方法 a 内部调用方法 c 会导致以下结果:

b from class Z
c from class X

我的第一个想法是输出如下:

b from class Z
c from class Z

希望我以现在有人可以帮助我的方式描述了这个问题。谢谢大家的回复。

最佳答案

确实会打印以下内容:

c from class X

因为cX中是私有(private),并且private methods aren't inherited in Java

A subclass does not inherit the private members of its parent class. However, if the superclass has public or protected methods for accessing its private fields, these can also be used by the subclass.

所以,即使X的方法a调用了c方法,它也只能调用c > X 中的方法。 Z 中是否存在另一个名为 c 的方法并不重要; a只能调用X中的c方法。 Z 中的 c 方法不会覆盖 X 中的 c 方法,因为这是私有(private)的。

Z 中调用 c 方法的唯一方法是拥有 Z 引用并直接调用它,因为它不是私有(private)的.

Z z = new Z();
z.c();

将打印

c from class Z

关于Java继承和重写方法——修饰符的影响,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21867688/

相关文章:

java - BFS 图遍历 - 将新节点追加到邻接矩阵

C++ : Function call Compile-Time Error from a Template Class using Typename as Base

html - 覆盖表格的默认 CSS

java - 将 onClickListener 设置为 Bottom Sheet 布局中的按钮

java - 应用服务器和静态文件字符编码

java - 当子类对象存储在父类(super class)数组中时,如何调用子类方法?

jQuery UI CSS 没有覆盖

swift - 覆盖作为 Obj-C 框架类一部分的 swift 函数

java - @Transactional 方法中所做的更改不会反射(reflect)到实体

c++ - 当基类为抽象时,声明子类的对象