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

Java继承方法的调用规则、可见性及静态/动态类型作用问询

Java继承与多态问题解析

先看示例代码:

public class Test {
    public static void main(String[] args) {
        A a = new A(3);
        A b = new B(1, 4);
        b.methodOne(6);       // <----- 此处,我认为会使用"b.m"和"b.increase"
    }
}

public class A {
    private int m;
    private int n;

    public A(int n) {
        m = n;
    }

    public void methodOne(int i) {
        m -= i;
        increase(i);
    }

    public void increase(int i) {
        m += 2 * i;
    }

    public void visibilityTest() {
        n++;                   // <----- 我认为调用b.visibilityTest()是可行的
                               // 因为它遵循A类的可见性规则
    }
}

public class B extends A {
    private int m;

    public B(int m, int n) {
        super(n);
        this.m = m + 1;
    }

    public void increase(int i) {
        m += i;
    }
}

如注释所述,假设执行b.methodOne(6)时,尽管methodOne继承自父类A,但会使用对象b的m属性与B类的increase方法(而非父类A的super.m)。针对这个场景,解答以下问题:


问题1:上述观点是否正确?继承方法通常会使用子类的方法与属性吗?

你的观点不完全正确,得分两部分看:

  • 关于increase方法:这部分是对的。Java的方法调用是动态绑定,只要子类重写了父类的方法,执行时会调用对象实际类型(也就是B类)的重写方法,所以methodOne里调用的increase(i)确实会执行B类的版本。
  • 关于m属性:这部分错了。Java的属性没有多态性,是静态绑定的。methodOne是A类的方法,里面直接写的m会指向A类自己的私有m,和B类里的m是两个完全独立的变量,彼此互不干扰。所以执行m -= i时,修改的是A类的m,不是B类的。

简单总结:继承的方法里,调用的方法会优先用子类重写的版本,但直接访问的属性是当前方法所在类的属性,不会自动用子类的同名属性。

问题2:在语句A b = new B(1,4)中,静态类型与动态类型分别起到什么作用?

  • 静态类型(A):属于编译期类型,编译器会根据这个类型检查你能调用哪些方法/属性。比如你不能通过b直接调用B类独有的方法,编译器会报错,因为它只认A类型有的成员。
  • 动态类型(B):是运行期的实际对象类型,决定了执行方法时到底调用哪个版本(比如重写的increase方法,就由动态类型B决定)。

一句话概括:编译阶段看静态类型做语法校验,运行阶段看动态类型执行实际逻辑。

问题3:继承方法是否遵循父类的可见性规则?例如,调用b.visibilityTest()时,能否访问父类A的私有属性n?

能正常访问,因为visibilityTest是A类定义的方法,方法的可见性权限是看方法所在的类,而不是调用该方法的对象类型。A类的方法可以访问自己的私有成员n,不管这个方法是被A类对象还是子类B的对象调用,执行时都能正常访问A类的n。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 02:00:38