Java 继承和覆盖方法 - 修饰符的影响
Posted
技术标签:
【中文标题】Java 继承和覆盖方法 - 修饰符的影响【英文标题】:Java inheritance and overwritten methods - The influence of modifiers 【发布时间】:2014-02-18 23:22:29 【问题描述】:我有以下四个类的问题:
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 中没有这样的方法,所以我们再次在方法 a 存在的类 X 中执行它。 首先我们执行方法b,因为你的对象是Z类的一个实例,而方法b在Z类中被覆盖导致输出
b from class Z.
之后调用方法 c(在方法 a 中)。由于我们的实例仍然是来自类 Z 的实例,并且在这个类中存在一个方法 c,你可以想出输出的想法
c from class Z
会发生。但这不是真的,因为类 X 中的 c 方法是私有方法。由于它是私有的,它不能被继承到子类(它甚至不能被看到)。所以没有必要让任何从 X 继承的类也有 c 方法。是不是因为从方法 a 调用 c 会导致调用 X 类而不是 Z 类中的 c 方法?
所以概括一下: 我上面的解释是正确的还是我遗漏了什么?我只是有点困惑,虽然我的实例来自类 Z,但从方法 a 内部调用方法 c 会导致以下结果:
b from class Z
c from class X
我的第一个想法是输出看起来像:
b from class Z
c from class Z
希望我以现在有人可以帮助我的方式描述了这个问题。谢谢大家的回复。
【问题讨论】:
请注意:您说,“编译器在每个超类中查找是否存在构造函数”。所有这些类都有构造函数。如果源代码中没有,编译器将生成一个默认的无参数构造函数,它只是调用超类构造函数。 【参考方案1】:这确实会被打印出来:
c from class X
因为c
在X
和private methods aren't inherited in Java 中是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
【讨论】:
好的,太好了。感谢您的快速答复。【参考方案2】:是的,你是对的。在方法 a() 中的类 X 中:
void a()
b();
c();
只有类 X 中的方法 c() 是可见的。因为从X班里面看不到Z班。
【讨论】:
【参考方案3】:编译器可以静态解析 c() 它是 de X 类中的私有方法,不需要动态解析,这意味着私有方法没有多态行为。
认为 c() 是 a() 实现的一部分,它是一个实现细节,想象一下您在 X 中将名称从 c 更改为 c1,...类中的方法名?,语言必须确保这样的更改不会对孩子产生影响。
【讨论】:
以上是关于Java 继承和覆盖方法 - 修饰符的影响的主要内容,如果未能解决你的问题,请参考以下文章