Java 重写 Override 与重载 Overload 区别、访问修饰符、static 关键字

前言

Java 面向对象面试有一套连环组合题:重载 & 重写、访问修饰符、static 关键字。

不少人的误区:

  1. 以为返回值不同就可以构成重载;
  2. 以为静态方法可以重写;
  3. 分不清 protected 在不同包子类的访问权限;
  4. 搞混静态代码块、构造代码块、构造方法执行顺序。

本文一站式搞定这一组高频考点:从底层定义、完整代码实战、边界规则、误区解析、工程选型,全部覆盖。适合 Java 基础巩固,也适合集中复盘。

一、重载 Overload

1. 核心定义

重载发生在同一个类内部 :多个方法方法名相同,参数列表不同。 参数列表不同包含三种情况:

  • 参数个数不同
  • 参数类型不同
  • 参数顺序不同(不同类型参数调换顺序)

重点:返回值、访问修饰符不能作为重载的判断条件 。编译器在调用方法时,只看传入实参,无法通过返回值类型区分调用哪个方法。仅返回值不一样,编译报错,不构成重载。 重载属于编译期静态绑定,在编译阶段就确定调用哪个方法,也叫静态多态。

2. 代码实战示例

java 复制代码
public class OverloadDemo {
    // 无参方法
    public void say() {
        System.out.println("无参数方法");
    }

    // 一个参数
    public void say(String name) {
        System.out.println("姓名:" + name);
    }

    // 两个参数
    public void say(String name, int age) {
        System.out.println("姓名:" + name + ",年龄:" + age);
    }

    // 参数顺序不同,构成重载
    public void say(int age, String name) {
        System.out.println("年龄:" + age + ",姓名:" + name);
    }

    public static void main(String[] args) {
        OverloadDemo demo = new OverloadDemo();
        demo.say();
        demo.say("张三");
        demo.say("李四",20);
        demo.say(22,"王五");
    }
}

3. 重载的使用场景

  • 构造方法重载:无参构造、带参构造,方便外部以不同方式实例化对象;
  • API 工具类:同一个功能,支持多种入参形式(例如日期格式化,支持传入 Date、String);
  • 框架底层大量使用:IO、集合、Spring 工具方法大量使用重载提升 API 易用性。

二、重写 Override

1. 核心定义

重写发生在存在继承关系的父子类之间 。子类对父类的实例方法 重新实现,覆盖父类原有逻辑。 @Override注解:编译期校验,检查当前方法是否满足重写规范,防止手敲写错方法名、参数类型,避免误以为重写成功。

重写约束规则

  1. 方法名、参数列表必须与父类完全一致;支持协变返回值(子类返回值可以是父类返回值的子类);
  2. 子类方法访问权限不能小于父类;父类 public,子类不能改为 protected/private;
  3. 子类抛出的受检异常范围不能大于父类抛出的受检异常;非受检异常无限制;
  4. 父类被 private /static/final 修饰的方法,不能重写;
  5. 重写针对实例方法,依靠虚方法表实现动态绑定,运行期确定执行方法,属于真正多态。

2. 代码实战示例

java 复制代码
class Parent {
    public void hello() {
        System.out.println("父类 hello 方法");
    }

    protected Person getPerson(){
        return new Person();
    }
}

class Child extends Parent {
    // @Override 校验重写
    @Override
    public void hello() {
        System.out.println("子类 hello 重写方法");
    }

    // 协变返回:返回子类对象Student,属于合法重写
    @Override
    public Student getPerson(){
        return new Student();
    }
}

class Person{}
class Student extends Person{}

public class OverrideTest {
    public static void main(String[] args) {
        Parent p = new Child();
        p.hello(); // 执行子类重写方法:多态
    }
}

3. 重载 VS 重写完整对比表

对比维度 重载 Overload 重写 Override
发生范围 同一个类内部 存在继承关系的父类与子类之间
方法签名 方法名相同,参数列表不同 方法名、参数列表完全一致
返回值 返回值不参与重载判断,无强制约束 支持协变返回,返回值必须是父类返回值的子类或本身
异常声明 无任何异常限制 子类抛出的受检异常不能比父类更广
访问权限 无权限限制,可以任意修改 子类访问权限不能低于父类
绑定时机 编译期静态绑定(静态多态) 运行期动态绑定(动态多态)
注解 不需要注解 推荐添加 @Override,编译校验
适用对象 普通成员方法、构造方法 仅实例方法,static/private/final 方法无法重写

4. 高频误区深度解析

误区 1:返回值不同就可以构成重载

纠正:编译器调用方法只看传入实参,无法依靠返回值区分,只修改返回值编译报错。

误区 2:静态方法可以重写

纠正:static 属于类,不属于实例对象。子类同名静态方法只是静态隐藏,不是重写,不存在多态。父类引用指向子类对象,调用静态方法执行的是父类静态方法。

java 复制代码
class Father{
    public static void test(){
        System.out.println("父类静态方法");
    }
}
class Son extends Father{
    public static void test(){
        System.out.println("子类静态方法");
    }
}
public class Test{
    public static void main(String[] args) {
        Father f = new Son();
        f.test(); // 输出父类静态方法!没有多态
    }
}

误区 3:父类 protected 方法,子类重写可以改成 private

纠正:编译报错!重写要求子类权限不能小于父类,protected > private,不允许降级。

三、Java 四种访问修饰符 public /protected/default /private

访问修饰符控制类、成员变量、成员方法 的可见范围,编码遵循最小权限原则:能小范围访问,就不要扩大权限,减少对外暴露,降低维护成本。

default:不写任何修饰符,也叫包访问权限。

修饰符 同一类 同一个包 不同包子类 其他包无关类
public ✅ ✅ ✅ ✅
protected ✅ ✅ ✅ ❌
default (不写) ✅ ✅ ❌ ❌
private ✅ ❌ ❌ ❌

各修饰符详解 & 工程选型建议

  1. private(优先推荐) 仅当前类内部可访问。封装的核心实现手段,成员变量优先定义 private。只暴露必要 get/set。
  2. default(包访问权限) 同包下所有类可以访问,跨包(哪怕是子类)也无法访问。项目内部包内工具类使用;业务实体尽量避免使用,可控性差。
  3. protected 同包类 + 不同包的子类可以访问。用于父类预留扩展点,给子类重写;业务开发谨慎使用,对外暴露范围偏大。
  4. public 所有包全部可见。用于对外暴露 API、接口、对外工具方法。public 暴露越多,后续改动兼容性成本越高。

坑点

很多人以为 protected,所有子类都能访问。

必须区分:同包子类直接访问;不同包子类,只能通过子类实例访问父类 protected 成员,不能用父类对象访问。

四、static 关键字详解|静态变量、静态方法、静态代码块

static 修饰的内容属于类本身 ,不属于实例对象。在类加载阶段完成初始化,早于对象实例创建,内存只分配一份,所有对象共享。

4.1 static 修饰静态变量(类变量)

java 复制代码
public static String schoolName;
  • 属于类,所有实例共享同一块内存;修改一处,全部对象可见;
  • 类加载时初始化,只初始化一次;
  • 推荐调用方式:类名.静态变量,不推荐对象.静态变量(语法允许,但可读性差);
  • 并发风险:多线程同时修改静态变量,极易出现线程安全问题。

4.2 static 修饰静态方法(类方法)

java 复制代码
public static void show(){

}
  • 静态方法只能直接访问静态成员(静态变量、静态方法);
  • 静态方法内部不能直接使用 this、super 关键字;
  • 静态方法无法访问非静态成员(非静态变量 / 非静态方法),因为调用静态方法时,可能对象还没有创建;
  • 静态方法不存在重写,只有静态隐藏,不具备多态。

4.3 static 静态代码块

java 复制代码
static {
    System.out.println("静态代码块执行");
}
  • 类加载的时候执行,整个生命周期只执行一次;
  • 执行时机早于构造代码块、构造方法;
  • 典型用途:加载配置文件、初始化静态资源、注册驱动;

4.4 代码演示执行顺序

java 复制代码
public class StaticExecuteDemo {
    static {
        System.out.println("1.静态代码块");
    }

    {
        System.out.println("2.构造代码块(每次new都会执行)");
    }

    public StaticExecuteDemo() {
        System.out.println("3.构造方法");
    }

    public static void main(String[] args) {
        System.out.println("main方法开始");
        new StaticExecuteDemo();
        new StaticExecuteDemo();
    }
}

输出结果:

复制代码
1.静态代码块
main方法开始
2.构造代码块(每次new都会执行)
3.构造方法
2.构造代码块(每次new都会执行)
3.构造方法

执行顺序总结: 静态代码块(类加载一次) → 构造代码块(每次 new 执行) → 构造方法(每次 new 执行)

4.5 static 高频踩坑清单

  1. 静态变量全局共享,多线程并发修改会产生线程安全问题;
  2. 静态方法不能直接调用非静态成员;非静态方法可以访问静态成员;
  3. 静态方法不存在多态,子类同名静态方法只是隐藏父类静态方法;
  4. 静态代码块只在类加载执行一次,不是创建对象就执行;
  5. 不要在静态代码块做耗时 IO 操作,会阻塞类加载,影响项目启动速度。

五、深度问答

Q1:重载和重写的区别?

A:重载发生在同一个类,方法名相同参数列表不同,编译期静态绑定。 重写发生在父子类之间,子类重写父类实例方法,方法签名一致,运行期动态绑定,支持多态。重写有异常、权限、返回值约束;重载没有权限、异常约束。
Q2:四种访问修饰符的范围,开发遵循什么原则?

A:private 仅本类;default 同包;protected 同包 + 不同包子类;public 全部包可见。开发遵循最小权限原则,能私有就不扩大访问范围。
Q3:static 的特点,静态方法和非静态方法互相访问规则?

A:static 修饰的内容属于类,类加载时初始化。静态方法只能直接访问静态成员;非静态方法可以访问静态成员。静态方法内部没有 this、super。
Q4:静态代码块什么时候执行?static 代码块、构造代码块、构造方法顺序?

A:静态代码块在类加载阶段执行,仅执行一次。执行顺序:静态代码块 → 构造代码块 → 构造方法。每次 new 对象,都会执行构造代码块和构造方法。
Q5:父类 protected 方法,子类重写能不能改成 public?能不能改成 private?

A:可以改成 public(权限扩大),不能改成 private(权限缩小,编译报错)。重写要求子类访问权限不能低于父类。
Q6:静态方法能不能重写?为什么?

A:不能重写。static 属于类,不是实例方法。子类同名静态方法只是隐藏父类静态方法,不存在虚方法表动态绑定,没有多态。

六、总结

  1. 重载:优化 API 设计,给调用方多种入参选择,提升易用性;
  2. 重写:配合多态,实现面向抽象编程,是策略模式、框架扩展的基础;重写记得加上@Override;
  3. 访问修饰符:坚持最小权限原则,成员变量优先 private;谨慎使用 protected、public;
  4. static:静态资源慎用,静态变量共享带来线程安全风险;静态代码块适合一次性初始化轻量资源,不要做耗时操作。

结语

重载、重写、访问修饰符、static 关键字是 Java 面向对象体系里一套组合考点。很多时候都会结合 OOP 三大特性一起提问,比如:重写的权限限制、静态方法能不能多态。 学习的时候不要孤立记忆知识点,把语法规则、底层绑定、工程实践结合起来,才可以从容应对追问。

相关推荐
Evand J1 小时前
【MATLAB例程】平面下,5基站对待定位点的定位。基于距离辅助下的AOA。完整代码下载链接
开发语言·matlab·平面·定位·导航·测距·aoa
GIS数据转换器1 小时前
基于CIM的城市智慧供热监管服务平台
java·大数据·开发语言·人工智能·后端·物联网·struts
weixin_417396831 小时前
星级酒店境外电视频道怎么合法接入?合规要点与核对清单
开发语言·前端·php·1024程序员节·综合布线
熊猫钓鱼>_>2 小时前
鸿蒙PC构建实战:hvigor modelVersion 降级 + schema 清理 + ArkTS 编译三连坑完整复盘
开发语言·华为·ai编程·harmonyos·openharmony·数据·ai生成
m0_639906942 小时前
SpringBoot自动配置原理
java·spring boot·后端
FRing032 小时前
JavaScript入门到精通三十一(原型继承、原型链)
开发语言·前端·javascript
1024奇点2 小时前
【仓颉语言入门 · 第二篇 第 12 课】
开发语言·数据库·ide·mysql·开源
LDR0062 小时前
LDR6100 智能遥控器精品软文:Type-C 充电口与低功耗量产维护
c语言·开发语言
海鸥-w2 小时前
数据库冗余字段设计笔记
java·数据库·笔记·oracle