Java向上转型时父类可变参数方法优先执行的原因解析
向上转型场景下父类可变参数方法被优先调用的原因
先看你提供的示例代码:
public class Test { public static void main(String[] args) { A a = new B(); a.foo("123"); } } class A { public void foo(String... s) { System.out.println("A"); } } class B extends A { public void foo(String s) { System.out.println("B"); } }
这段代码运行结果是打印A,核心原因是子类的foo(String s)并没有重写父类的foo(String... s),只是方法重载,再结合Java的方法绑定规则导致的:
1. 方法重写的前提不满足
Java里方法重写要求方法签名(方法名+参数列表)完全一致。父类的String... s是可变参数语法糖,本质等价于String[] s;而子类的foo(String s)参数是单个String,两者参数类型完全不同,所以这是子类新增的一个重载方法,而非对父类方法的重写。
2. 编译期的方法匹配逻辑
当你用父类类型A的引用调用foo("123")时,编译器只会在A类的方法中寻找匹配的方法:
A类只有foo(String...)这一个方法,编译器会自动把单个String参数包装成长度为1的String[](可变参数的语法特性),因此编译阶段就确定了要调用的是A类的foo(String...)方法。
3. 运行期的动态绑定不生效
Java的动态绑定(运行时根据实际对象类型调用方法)只针对被重写的方法。由于子类B并没有重写A的foo(String...),运行时找不到对应的重写实现,自然就执行父类A的方法逻辑。
如果想让子类的方法被调用,有两种方式:
- 把引用强制转换为
B类型:((B)a).foo("123"),此时编译器会匹配B类的foo(String s) - 让子类重写父类的可变参数方法:在
B类中添加public void foo(String... s) { System.out.println("B"); }
内容的提问来源于stack exchange,提问作者Artur
相关产品推荐
相关产品推荐

