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

Java中为何私有方法按引用类型调用、公有方法按对象类型调用?

Java私有方法调用解析的疑问解答

先看你的代码和实际输出:

代码

class Main {
    public static void main(String[] args) {
        Main m = new Sub();
        m.sing();
        System.out.println(m.foo()+"");
    }

    public void sing(){
        System.out.println("hohoho");
    }
    
    private boolean foo(){
        return false;
    }
    
}

class Sub extends Main{
    
    public boolean foo(){
        return true;
    }
    
    public void sing(){
        System.out.println("lalala");
    }
}

实际输出

lalala
false

核心解释

你的“对象类型决定方法调用”的假设只适用于可重写的实例方法,并非所有方法都遵循这个规则,这是你困惑的根源。

1. 为什么foo()调用了Main类的实现?

  • Main类中的foo()是私有方法,私有方法在Java中是静态绑定的:编译器在编译阶段就会根据变量的引用类型(这里是Main)确定要调用的方法,完全不会考虑运行时的实际对象类型(Sub)。
  • Sub类中的foo()并不是重写Main的foo(),而是一个全新的独立方法——因为私有方法无法被子类继承,Sub根本看不到Main的foo(),所以它的foo()是自己定义的、和Main的foo()毫无关联的方法。
  • 当你用Main类型的引用m调用foo()时,编译期就已经锁定了Main类的私有foo(),运行时不会做动态查找,自然不会执行Sub的foo()。

2. 关于“对象类型决定方法调用”的适用范围

这个规则仅针对可重写的实例方法,需要满足三个条件:

  • 非private
  • 非static
  • 非final
    这类方法才会在运行时根据对象的实际类型进行动态绑定,也就是你理解的“对象类型决定调用哪个实现”。而私有方法、静态方法、final方法都是静态绑定,编译期就确定了方法版本。

3. 为什么sing()调用了Sub类的实现?

sing()是public的实例方法,属于可重写的范围,所以运行时会根据实际对象类型Sub,调用Sub中重写后的sing()方法,输出lalala。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 02:56:03