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

Java继承和重写方法-修饰符的影响,java,inheritance,overriding,modifiers,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()

我对以下四个类有问题:

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();
    }

}
请不要评论这些类的合理性,这只是一个例子。我还尝试通过使用eclipse调试器的方法跟踪JVM的流程,但是这些方法的步骤在某些点上有点太快了

我已经知道了

Y y = new Z();
创建Z类的新实例,并将其指定给Y类的引用。由于Z中没有构造函数,编译器在每个超类中查找是否有构造函数,如果没有,则使用对象类的构造函数。 在那之后

y.a();
方法被调用。在类Z中没有这样的方法,所以我们再次在类X结束,在那里方法a存在并执行它。 首先,我们执行方法b,因为您的对象是类Z的实例,并且方法b在类Z中被覆盖,从而导致输出

b from class Z.
c from class Z
然后调用方法c(在方法a中)。因为我们的实例仍然是来自类Z的实例,并且在这个类中存在一个方法c,所以您可以想到输出

b from class Z.
c from class Z
将会发生。但这不是真的,因为类X中的c方法是私有方法。因为它是私有的,所以不能被继承到子类(甚至不能被看到)。因此,不需要任何从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

我希望现在有人能帮我解决这个问题。谢谢您的回复。

是的,您是对的。在方法a()中的类X中:


只有类X中的方法c()可见。这是因为从X类内部看不到Z类。

这确实会被打印出来:

c from class X
因为
c
X
中是
private
,并且

子类不继承其父类的私有成员。但是,如果超类具有访问其私有字段的公共或受保护方法,则子类也可以使用这些方法

因此,即使
X
的方法
a
调用
c
方法,它也只能调用
X
中的
c
方法。在
Z
中是否存在另一种称为
c
的方法并不重要
a
只能调用
X
中的
c
方法。
Z
中的
c
方法不会覆盖
X
中的
c
方法,因为它是私有的

Z
中调用
c
方法的唯一方法是使用
Z
引用并直接调用它,因为它不是私有的

Z z = new Z();
z.c();
哪个会打印

c from class Z

编译器可以静态地解析c()是dex类中的私有方法,不需要动态解析,这意味着私有方法没有多态行为


认为c()是a()实现的一部分,这是一个实现细节,想象一下,你在X中将名称从c更改为c1,你希望在类中更改私有方法名称时有不同的行为吗?语言必须确保这样的更改不会对子类产生影响。

好的,很好。谢谢你的快速回答。注意:你说,“编译器在每个超类中查找是否有构造函数”。所有这些类都有构造函数。如果源代码中没有,编译器将生成一个默认的无参数构造函数,该构造函数只调用超类构造函数。