You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中Dynamic Binding、Overriding/Overloading调用问题解惑

Java方法绑定与继承问题解答
public abstract class Vector{
    public abstract double norm();
}
public class PlanarVector extends Vector {
    protected final double x;
    protected final double y;
    public PlanarVector(double x, double y){
        this.x=x;
        this.y=y;
    }
    public double norm(){
        return Math.sqrt(x*x+y*y);
    }
    public PlanarVector sum(PlanarVector v){
        return new PlanarVector(x+v.x, y+v.y);
    }
    public String toString(){
        return "x=" + x + " y=" + y;
    }
}
public class SpaceVector extends PlanarVector {
    protected final double z;
    public SpaceVector(double x, double y,double z){
        super(x,y);
        this.z=z;
    }
    public double norm(){
        return Math.sqrt(x*x + y*y + z*z);
    }
    public SpaceVector sum(SpaceVector v){
        return new SpaceVector(x+v.x, y+v.y, z+v.z);
    }
    public String toString(){
        return super.toString() + " z=" + z;
    }
}

public class TestVector {
    public static void main ( String[] args ) {
        Vector v0 ;
        PlanarVector v1 , v2 ;
        SpaceVector v3 , v4 ;
        v1 = new PlanarVector ( 3 , 4 ) ;
        v0 = v1 ;
        v2 = new SpaceVector ( 2 , 3 , 6 ) ;
        v3 = new SpaceVector ( 2 , 1 , 0 ) ;
        v4 = v3 ;
        System.out.println(v1.sum(v2)) ; //expected output: x=5 y=7 realoutput: x=5 y=7 (v1 can only use PlanarVectorMethods because its dynamic and static type is PlanarVector)

        System.out.println(v2.sum(v1)) ; //expected output: x=5 y=7 realoutput: x=5 y=7
        System.out.println(v2.sum(v3)) ; //expected output: 'x=4 y=4 z=6'  realoutput: 'x=4 y=4'
        System.out.println(v3.sum(v2)) ; //expected output: 'x=4 y=4 z=6'  realoutput: 'x=4 y=4'
        System.out.println(v3.sum(v4)) ;
        System.out.println(v1.norm()) ;
        System.out.println(v2.norm()) ; //expected output: sqrt(13) realoutput: 7
    }
}

问题解答

1. 为何v2.sum(v3)未调用SpaceVector类的sum方法?

Java里方法重载是静态绑定,编译阶段就确定要调用的方法。v2的静态类型是PlanarVector,编译器只会查找PlanarVector及其父类中定义的sum方法。SpaceVector的sum方法参数是SpaceVector,这属于重载而非重写,编译器不认子类新增的重载方法,所以编译时绑定到PlanarVector的sum(PlanarVector),运行时自然不会调用SpaceVector的sum。

2. 为何v3.sum(v2)也未调用SpaceVector类的sum方法?

v3的静态类型是SpaceVector,但v2的静态类型是PlanarVector。方法重载匹配看参数的静态类型,而非实际动态类型。SpaceVector的sum(SpaceVector)要求参数是SpaceVector类型,而v2的静态类型是PlanarVector,编译器无法确定v2实际是SpaceVector实例,因此会匹配到从PlanarVector继承来的sum(PlanarVector)方法,而非SpaceVector自己的sum方法。

3. 为何v2.norm()又调用了SpaceVector类的norm方法?

norm()是重写方法:SpaceVector的norm和PlanarVector的norm方法签名完全一致(方法名、参数列表、返回值均匹配)。Java中重写方法是动态绑定,运行时根据对象的实际类型(动态类型)调用对应方法。v2的动态类型是SpaceVector,所以运行时执行SpaceVector的norm实现。

4. 父类引用指向子类实例时,为何无法调用子类独有方法,但可调用重写后的子类实现方法?

  • 无法调用子类独有方法:编译阶段编译器只校验引用的静态类型,父类中没有子类独有方法的定义,编译器会直接报错,无法进入运行阶段。
  • 可调用重写后的子类实现:重写方法采用动态绑定,运行时会根据对象的实际类型(动态类型)调用子类的实现,不管引用的静态类型是什么,只要实际对象是子类实例,就会执行子类的重写逻辑。

内容的提问来源于stack exchange,提问作者Mateusz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 04:35:51