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

技术咨询:请求详解method hiding(方法隐藏)的底层运行机制

理解方法隐藏(Method Hiding)的底层逻辑

Hey there! Let me break down method hiding for you clearly—no confusing jargon, just straight talk about what's happening under the hood.

先划重点:方法隐藏≠方法重写(Override)

很多人会把这俩搞混,所以先明确核心差异:

  • 方法重写是针对实例方法的动态绑定行为(运行时才决定调用哪个方法);
  • 方法隐藏则是针对静态方法(或父类私有方法)的静态绑定行为(编译阶段就锁定调用目标)。

(1) 方法隐藏实际执行了什么操作?

简单来说:当子类定义了一个和父类同名、同参数列表的静态方法时,子类的方法会“隐藏”父类的同名静态方法——但这不是“覆盖”,而是在编译期就固定了方法的调用指向,运行时不会根据对象的实际类型动态切换调用目标。

核心本质是:方法隐藏是编译阶段的静态绑定行为,JVM不会在运行时去检查对象的实际类型,只会看你用来调用方法的变量的「编译时类型」。


(2) 这些操作具体是怎样的?

我用代码例子一步步拆解给你看:

假设我们有父类和子类的静态方法定义:

class Animal {
    public static void eat() {
        System.out.println("Animal is eating");
    }
}

class Cat extends Animal {
    public static void eat() {
        System.out.println("Cat is eating");
    }
}

步骤1:编译阶段——锁定方法调用目标

当你写这样的代码时:

Animal animalRef = new Cat();
animalRef.eat(); // 调用的是Animal的eat(),不是Cat的!

编译器在编译时,只会关注animalRef的编译时类型(也就是Animal),所以它会直接绑定到Animal类的eat()静态方法,在生成的字节码里写入invokestatic指令,明确指向Animal.eat()。

而如果是这样的代码:

Cat catRef = new Cat();
catRef.eat(); // 调用的是Cat的eat()

编译器看到catRef的编译时类型是Cat,就会绑定到Cat类的eat()方法,字节码里的invokestatic指令直接指向Cat.eat()。

步骤2:运行阶段——直接执行编译期绑定的方法

运行时JVM看到invokestatic指令,会直接执行指令里指定的类的静态方法——完全不会去检查animalRef实际指向的对象是Cat类型。因为静态方法属于类本身,不属于实例,根本不需要依赖对象实例来确定调用目标。

对比方法重写,更能凸显差异

如果是实例方法的重写场景:

class Animal {
    public void sleep() {
        System.out.println("Animal is sleeping");
    }
}

class Cat extends Animal {
    @Override
    public void sleep() {
        System.out.println("Cat is sleeping");
    }
}

这时执行:

Animal animalRef = new Cat();
animalRef.sleep(); // 调用的是Cat的sleep()

编译器会生成invokevirtual指令,运行时JVM会根据animalRef实际指向的Cat对象,动态调用Cat的sleep()方法——这就是和方法隐藏完全不同的动态绑定逻辑。


额外补充:私有方法的隐藏

如果父类有个私有方法,子类定义了同名同参数的方法,这也算方法隐藏,但本质是子类的方法和父类的方法完全无关——因为私有方法不能被继承,子类的方法是全新的,只是名字碰巧一样。比如:

class Animal {
    private void run() {
        System.out.println("Animal runs");
    }
}

class Cat extends Animal {
    public void run() {
        System.out.println("Cat runs");
    }
}

这时用Cat实例调用run(),完全和父类的run()无关,因为父类的run()对子类不可见,子类的run()是独立的方法,这也是一种隐藏,逻辑和静态方法隐藏类似:编译期就确定了调用目标。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:53:06