Java方法重写与多态问题:访问修饰符对执行结果的影响
Java方法调用与访问修饰符的疑问解析
问题场景与现象
场景1:带private修饰符的代码输出1
运行以下代码,输出结果为1:
public class Main { public static void main(String[] args) { A ref1 = new C(); B ref2 = (B) ref1; System.out.println(ref2.g()); } } class A { private int f(){ return 0; } public int g(){ return 3; } } class B extends A{ private int f(){ return 1; } public int g(){ return f(); } } class C extends B{ public int f(){ return 2; } }
场景2:强制转换前后调用g()均输出1
修改代码后,两次调用g()的输出都是1:
public class Main { public static void main(String[] args) { A ref1 = new C(); System.out.println(ref1.g()); B ref2 = (B) ref1; System.out.println(ref2.g()); } }
输出:
1 1
场景3:移除所有访问修饰符后输出2
移除public和private修饰符后,输出变为2:
public class Main { public static void main(String[] args) { A ref1 = new C(); B ref2 = (B) ref1; System.out.println(ref2.g()); } } class A { int f(){ return 0; } int g(){ return 3; } } class B extends A{ int f(){ return 1; } int g(){ return f(); } } class C extends B{ int f(){ return 2; } }
用户疑问:
- 为何强制转换前后调用
g()结果都是1? - 输出差异是否与
private和public修饰符有关?
核心解析
1. 带private修饰符时的运行逻辑
- private方法不支持继承和重写:Java中
private方法是当前类的私有成员,子类无法继承,更不能重写。所以B类的private f()和A类的private f()是完全独立的两个方法。 - B类的
g()中调用的f(),是自身的private f()——因为private方法是静态绑定,编译阶段就确定了调用目标,不会因为运行时对象的实际类型而改变。 - 虽然
ref1实际指向C对象,但C没有重写g(),调用g()时会动态绑定到父类B的g(),而B的g()固定调用自己的private f()返回1,所以无论引用是A还是B类型,结果都是1。
2. 移除访问修饰符后的运行逻辑
- 无修饰符的方法是默认包访问权限,这种权限下子类可以继承并重写方法。
- C类的
f()是真正重写了B类的f(),当B的g()调用f()时,因为f()是可重写的,会触发动态绑定,运行时调用实际对象(C)的f()返回2,所以最终输出2。
关于强制转换的疑问
强制转换仅改变引用的编译期类型,不会改变对象的实际类型。g()是public方法,始终根据对象实际类型动态绑定。第一个场景中C没有重写g(),所以无论引用是A还是B类型,都会调用B的g(),结果自然都是1。
内容的提问来源于stack exchange,提问作者Wax Yao
相关产品推荐
相关产品推荐

