
一、引言在 Java 面向对象编程中继承是实现代码复用与扩展的基础而方法重载Overload和方法重写Override则是构建多态特性的两大核心手段。这三者紧密相连共同构成了 Java 面向对象设计的基石也是面试中高频考察、日常开发中极易混淆的知识点。很多开发者能说出 “重载是同一个类中方法名相同参数不同重写是子类重写父类方法”但却说不清继承如何为多态提供了基础重载和重写在编译期与运行期的执行机制有何本质区别为什么静态方法不能被重写只能被隐藏实际编码中如何避免写出不符合规范的代码如误以为 “返回值不同也能重载”或重写时随意修改访问权限本文将从继承的本质出发系统梳理继承、方法重载与重写的语法规则、执行机制和设计场景帮你不仅 “知其然”更 “知其所以然”真正吃透 Java 多态的核心。二、继承2.1 定义继承是 Java 面向对象三大特性封装、继承、多态之一核心是让子类Subclass复用父类Superclass的代码和特性同时可扩展自定义逻辑。语法上通过extends关键字实现三、字段3.1 继承子类继承父类字段的核心规则是访问权限控制static/final等修饰符不影响 “继承性”只影响 “可修改性 / 共享性”。父类字段访问权限子类是否继承关键说明public✅ 是子类可直接访问、修改除非字段是 finalprotected✅ 是子类同包 / 不同包均可访问不同包的非子类不可访问default缺省✅ 是仅同包子类可访问不同包子类无法访问private❌ 否私有字段仅父类自身可见子类无法直接继承 / 访问可通过父类的 public/protected getter/setter 间接操作3.2 访问static字段子类继承后本质是共享父类的静态字段通过子类名.静态字段访问时实际指向父类的静态内存空间final字段子类继承后可访问但无法修改final 约束 “不可赋值”。普通字段非 static、非 final子类继承后可直接访问受访问权限限制支持自由修改其值每个子类实例都拥有独立的普通字段内存空间与其他实例互不影响。被隐藏的字段子类重定义父类同名字段子类实例中同时存在父类字段和子类同名字段直接访问时优先使用子类自己的字段若要访问父类被隐藏的字段必须通过super.字段名显式调用两者内存独立互不覆盖。未被隐藏的字段子类未重定义子类直接继承父类字段访问时直接指向父类字段的内存空间无额外遮蔽语义清晰推荐使用。3.3 隐藏字段隐藏Field Hiding是指子类定义了与父类同名的字段无论类型、访问权限、修饰符是否一致导致子类中直接访问该字段时优先指向子类自身定义的版本父类的同名字段并未被覆盖 / 删除只是被 “遮蔽”—— 两者在内存中独立存在是 Java 继承中极易被误解的核心概念。字段只有 “隐藏”没有 “重写”这是和方法最本质的区别。3.4 无多态字段访问的规则是 “看引用类型不看实际对象类型”// 父类引用指向子类实例模拟多态场景 Parent p new Child(); // 仍访问父类字段无多态 System.out.println(p.info); // 输出父类原始字段Java 设计字段时选择 “编译时绑定”而非方法的 “运行时绑定”核心原因性能考量字段访问是直接的内存地址读取编译时绑定能减少运行时开销方法重写需要通过方法表动态查找有性能损耗语义安全字段代表对象的 “状态”若支持运行时绑定会导致父类定义的字段语义被子类随意篡改破坏封装性逻辑一致性字段是 “数据”方法是 “行为”—— 多态的核心是 “行为的动态变化”而非 “数据的动态替换”。四、内部类4.1 继承父类内部类类型子类是否继承关键说明public/protected 静态内部类✅ 是子类可通过子类名.静态内部类直接访问无需父类实例public/protected 非静态内部类✅ 是子类需先创建父类子类实例再通过实例.new 非静态内部类访问private 内部类❌ 否仅父类自身可见子类无法访问4.2 隐藏子类无法 “重写Override” 父类的内部类无论是静态还是非静态只能定义 “同名的新内部类”—— 本质是「内部类的隐藏Hiding」所以父类的内部类被final修饰也行而非重写。无继承关系子类同名内部类和父类内部类是两个完全独立的类彼此无继承 / 重写关系编译时绑定访问子类.InnerClass时编译器直接指向子类的内部类与父类无关访问父类内部类的唯一方式显式指定父类名.InnerClass静态或父类实例.new InnerClass()非静态4.3 访问访问父类「静态内部类」未被隐藏子类无同名静态内部类直接用父类名.静态内部类名或简化为静态内部类名子类继承后可直接用。已被隐藏子类定义了同名静态内部类必须用父类名.静态内部类名不能简化绕过子类的同名隐藏访问父类「非静态内部类」未隐藏可通过this.new 内部类名简化访问已隐藏必须通过super.new 内部类名或父类实例.new 父类.内部类名访问4.4 无多态内部类无论静态 / 非静态完全不支持多态所有访问都是「编译时绑定」—— 访问结果只看代码中写的 “类型声明”和 “实际对象类型” 无关。静态内部类是 “类级成员”完全不存在多态的可能 —— 哪怕试图用 “父类内部类引用指向子类内部类实例”编译器直接报错类型不兼容因为两者是完全独立的类无继承关系。五、构造方法5.1 无法继承Java 中子类永远无法继承父类的构造方法 —— 这是继承规则中最核心的特例之一。构造方法的作用是 “初始化当前类的实例”属于类的 “专属初始化逻辑”仅能由当前类调用无法被子类继承复用。很多开发者误以为 “子类能调用父类构造方法” 就是 “继承”但调用 ≠ 继承调用是复用父类的初始化逻辑继承是子类拥有父类的方法可直接重写 / 调用两者本质不同。语义冲突构造方法的方法名必须和类名完全一致如Parent()属于Parent类Child()属于Child类子类无法继承一个 “和自己类名不同” 的构造方法初始化安全构造方法负责初始化类的私有字段、核心资源若允许继承子类可能绕过父类的初始化逻辑破坏对象的完整性设计初衷构造方法是 “创建实例的入口”每个类需自定义自己的初始化逻辑继承会导致子类实例初始化失控。5.2 构造方法的调用子类虽不能继承父类构造方法但可通过super()关键字调用父类构造方法完成父类部分的初始化若子类构造方法中未显式写super()编译器会自动在子类构造方法的第一行添加super()调用父类的无参构造若父类没有无参构造仅定义了有参构造子类必须显式调用父类的有参构造super(参数)否则编译报错super()必须是子类构造方法的第一行代码子类构造方法中super()和this()调用子类其他构造方法不能同时出现若父类只有私有构造方法private则该类无法被继承子类无法调用父类私有构造子类构造方法最多只能调用一次父类构造方法5.3 无多态多态的核心是 “运行时动态绑定”—— 父类引用指向子类实例时执行子类重写的方法逻辑。但构造方法从设计上就彻底排除了多态的可能构造方法不能被继承子类无法重写父类构造方法无重写则无多态的基础构造方法的调用是编译时绑定仅由 “new 关键字后的类名” 决定与引用类型无关构造方法的唯一作用是 “初始化当前类实例”无需也不能动态切换逻辑。多态的核心是 “方法的动态执行”而非 “引用的赋值”Parent p new Child();中只是把 “子类实例的内存地址” 赋值给 “父类类型的引用变量”这是多态的语法前提但不是多态本身六、方法6.1 继承父类方法访问权限能否继承关键说明示例public公有✅ 能子类同包 / 不同包均可继承、直接调用、重写final 方法除外public void test() {}→ 子类可直接test()调用protected受保护✅ 能子类同包 / 不同包均可继承不同包的非子类无法访问protected void doLogic() {}→ 不同包子类可继承调用default缺省 / 包私有✅ 能仅同包子类可继承不同包子类无法继承 / 访问void print() {}→ 同包子类可调用不同包不行父类方法修饰符能否继承继承后约束static静态✅ 能子类可继承 / 调用但不能重写子类定义同名静态方法属于 “隐藏”而非重写final最终✅ 能子类可继承 / 调用但不能重写编译报错abstract抽象✅ 能子类必须重写除非子类也是抽象类否则编译报错static final✅ 能子类可继承 / 调用既不能重写也不能隐藏后修改逻辑推荐用于工具类方法6.2 隐藏子类定义了与父类同名的静态方法导致子类中直接调用该方法时优先指向子类自身的版本父类的同名方法并未被覆盖只是被 “遮蔽”—— 这是 Java 继承中与 “方法重写Override” 极易混淆的概念且仅针对static方法 /private方法生效。只有静态方法 /会发生 “隐藏”非静态的实例方法只会发生 “重写”不会隐藏方法隐藏是编译时绑定无多态特性与方法重写的 “运行时绑定” 本质不同。private 方法不会被继承子类根本看不到这个父类 private 方法子类写同名同参 private 方法只是子类自己新增的独立方法语法上既不是重写也不是隐藏final无法被重写直接报错6.3 方法重写和方法重载对比维度方法重写Override方法重载Overload核心定义子类覆盖父类中方法名 参数列表完全相同的方法替换其实现逻辑同一个类中定义方法名相同、参数列表不同的多个方法适配不同参数场景发生范围父子类之间继承关系同一个类内部子类也可对父类方法重载方法名必须完全相同必须完全相同参数列表必须完全相同个数 / 类型 / 顺序均一致必须不同个数 / 类型 / 顺序任意一个不同即可返回值需兼容Java5 支持协变子类返回值是父类的子类型不能随意修改无要求仅返回值不同≠重载访问权限子类方法权限不能比父类更严格如父类 public子类不能 private无要求可任意修改异常抛出子类抛出的异常不能比父类更宽泛可更少 / 更具体无要求可任意修改final影响父类 final 方法不能被重写final 方法可以被重载static影响静态方法不能被重写子类静态方法只是隐藏父类方法静态方法可以被重载核心目的子类定制 / 扩展父类的方法逻辑体现多态简化调用一个方法名适配多种参数场景方法调用逻辑运行时绑定多态看对象实际类型编译时绑定看调用时的参数类型 / 个数注解使用推荐加Override注解编译器校验规则无专属注解示例父类public void say()→ 子类public void say()类内add(int a)→add(int a, int b)→add(double a)6.4 多态多态同一个行为方法调用作用在不同对象上表现出不同的结果。关键逻辑父类引用指向子类对象时调用重写方法执行的是子类的实现而不是父类的—— 这就是重写带来的多态效果。6.5 访问场景调用前提访问目标具体操作方法核心子类内部方法已被重写父类方法写super.方法名(参数)子类内部方法未被重写父类方法直接写方法名(参数)继承子类内部任意情况子类方法直接写方法名(参数)外部类子类对象调用父类方法1. 子类写中转方法内部用 super外部调中转方法2. 新建父类对象调用外部类子类对象调用子类方法子类对象.方法名 (参数)外部类父类引用指向子类对象父类方法新建纯父类对象.方法名 (参数)外部类父类引用指向子类对象子类方法父类引用.方法名 (参数)多态任意场景静态方法父类方法父类名.静态方法名 (参数)任意场景静态方法子类方法子类名.静态方法名 (参数)任意场景父类 private 方法父类方法调用父类的公有方法间接访问七、问题7.1 返回值同一个类中仅返回值不同 → 编译报错不算重载父子类之间仅返回值不同 → 不构成重写大概率编译报错返回值不满足协变 → 编译报错不构成重写返回值满足协变 → 合法重写7.2 访问权限同一个类中仅访问权限不同 → 编译报错不算重载父子类之间仅访问权限不同 → 可能编译报错子类重写方法的访问权限不能比父类更严格子类比父类严格编译错误子类方法的权限和父类一致或更宽松这是合法的重写但 “仅改权限” 本身不会让方法变成 “新方法”只是调整了方法的访问范围7.3 异常同一个类中仅异常声明不同 → 编译报错不算重载父子类之间仅异常声明不同 → 不构成重写大概率编译报错子类重写方法抛出的受检异常不能比父类方法声明的异常范围更广不能抛出父类未声明的新受检异常否则编译报错不构成重写子类重写方法抛出的受检异常与父类相同或为父类异常的子类或不抛出受检异常 → 合法重写运行时异常RuntimeException及其子类不受此限制子类可自由抛出