杰瑞科技汇

Java方法重写与重载,核心区别在哪?

核心概念总结(一句话区分)

  • 方法重载一个类中,方法名相同,参数列表不同(参数个数、类型或顺序不同),编译时多态,与返回值类型无关。
  • 方法重写子类中,方法名、参数列表、返回值类型(或其子类)必须与父类完全相同(除了 privatefinal 方法),运行时多态,是对父类方法功能的“重新实现”。

详细对比表格

特性 方法重载 方法重写
定义位置 同一个类中,或者在父子类中 必须有继承关系的类中,子类重写父类的方法。
方法名 必须相同 必须相同
参数列表 必须不同
(参数个数、类型、顺序至少有一项不同)
必须完全相同
(参数个数、类型、顺序都必须一样)
返回值类型 可以相同,也可以不同
(如果不同,必须是不同参数类型的返回值,否则会编译报错)
必须相同或是其子类
(Java 5+ 协变返回类型)
访问修饰符 没有限制。 子类方法的访问权限不能比父类更严格
(父类是 public,子类不能是 protected
异常抛出 没有限制。 子类方法抛出的异常不能比父类更宽泛(不能是父类异常的父类)。
@Override 注解 不使用 强烈建议使用,用于编译器检查,确保正确重写。
触发时机 编译时决定调用哪个方法。 运行时决定调用哪个方法(通过对象的实际类型)。
核心思想 “一个类,多种功能”
提供同一功能的多种版本,根据传入参数不同选择执行。
“子类特化”
子类根据自身需求,重新实现从父类继承来的方法。
英文 Overloading Overriding

详细解释与代码示例

方法重载

核心规则:方法名相同,参数列表不同。

Java方法重写与重载,核心区别在哪?-图1
(图片来源网络,侵删)

重载让一个类可以根据传入参数的不同,提供多种“版本”的功能,使代码更直观、易用。

示例:一个 Calculator

public class Calculator {
    // 重载方法 1: 两个整数相加
    public int add(int a, int b) {
        System.out.println("执行 int add(int, int)");
        return a + b;
    }
    // 重载方法 2: 三个整数相加 (参数个数不同)
    public int add(int a, int b, int c) {
        System.out.println("执行 int add(int, int, int)");
        return a + b + c;
    }
    // 重载方法 3: 两个 double 相加 (参数类型不同)
    public double add(double a, double b) {
        System.out.println("执行 double add(double, double)");
        return a + b;
    }
    // 错误示例:这不是重载,编译器会报错 "duplicate method"
    // 因为参数列表完全相同 (int, int)
    // public long add(int x, int y) { ... } 
}

调用方式:

public class Main {
    public static void main(String[] args) {
        Calculator calc = new Calculator();
        int sum1 = calc.add(10, 20);        // 调用 add(int, int)
        int sum2 = calc.add(10, 20, 30);    // 调用 add(int, int, int)
        double sum3 = calc.add(10.5, 20.5); // 调用 add(double, double)
        System.out.println("sum1: " + sum1);
        System.out.println("sum2: " + sum2);
        System.out.println("sum3: " + sum3);
    }
}

编译时多态:在编译阶段,Java 编译器根据你传入的参数类型和数量,就能确定要调用哪个 add 方法,这个过程在编译时就完成了。

Java方法重写与重载,核心区别在哪?-图2
(图片来源网络,侵删)

方法重写

核心规则:在继承关系中,子类重新实现一个与父类方法签名完全相同(除了访问权限和异常)的方法。

重写是实现多态的关键,它允许子类对象在调用父类方法时,表现出子类特有的行为。

示例:AnimalDog

父类 Animal.java

Java方法重写与重载,核心区别在哪?-图3
(图片来源网络,侵删)
public class Animal {
    // 父类的方法
    public void makeSound() {
        System.out.println("动物发出声音");
    }
}

子类 Dog.java

public class Dog extends Animal {
    // 使用 @Override 注解,让编译器检查我们是否正确地重写了方法
    @Override
    public void makeSound() {
        // 子类提供了自己的实现
        System.out.println("汪汪汪!");
    }
}

调用方式:

public class Main {
    public static void main(String[] args) {
        Animal myAnimal = new Animal();
        Animal myDog = new Dog(); // 向上转型:父类引用指向子类对象
        myAnimal.makeSound(); // 输出: 动物发出声音
        myDog.makeSound();   // 输出: 汪汪汪!
    }
}

运行时多态:关键在于 myDog.makeSound() 这一行。

  • myDog编译时类型Animal,所以编译器检查 makeSound() 方法是否存在,它确实存在。
  • myDog运行时类型(或称实际类型)是 Dog
  • 在程序运行时,JVM 会根据对象的实际类型(Dog)去查找并执行 Dog 类中的 makeSound() 方法,而不是 Animal 类中的。

这就是为什么 myDog.makeSound() 输出的是 "汪汪汪!"。


关键区别与常见误区

参数列表 vs 方法签名

  • 重载关心的是参数列表不同。
  • 重写要求方法签名(方法名 + 参数列表)完全相同。

返回值类型

  • 重载:返回值类型可以不同,但前提是参数列表必须不同,如果两个方法只有返回值类型不同,而参数列表完全相同,则不是重载,是编译错误。

  • 重写:在 Java 5 之前,返回值类型必须完全相同,从 Java 5 开始,引入了协变返回类型,允许子类方法的返回值类型是父类方法返回值类型的子类。

    示例:

    class Parent {
        public Parent getObject() {
            return new Parent();
        }
    }
    class Child extends Parent {
        @Override
        public Child getObject() { // 返回 Child 是 Parent 的子类,所以可以重写
            return new Child();
        }
    }

privatefinal 方法

  • private 方法:不能被重写,因为它们对子类是不可见的,子类中如果定义一个与父类 private 方法签名相同的方法,那只是定义了一个新的、无关的方法,不是重写
  • final 方法:不能被重写,这保证了父类的核心逻辑不会被任何子类随意修改。

访问权限

  • 重写时,子类方法的访问权限不能比父类更严格

    • 父类 public -> 子类必须是 public
    • 父类 protected -> 子类可以是 protectedpublic
    • 父类默认(包私有) -> 子类可以是默认、protectedpublic
    • 父类 private -> 不能重写

    这是为了保证“里氏替换原则”(LSP):子类对象应该能够替换任何父类对象,并且程序行为不变,如果子类方法的访问权限更严格,那么一个父类类型的引用可能就无法调用子类中那个“更私有的”方法了。


重载 重写
中文 同一个类,方法名相同,参数不同 子类继承父类,方法名和参数都相同,功能重新实现
英文 Overloading Overriding
目的 方便调用,提供多种功能实现 实现多态,允许子类定制行为
关系 同一个类或父子类 必须有继承关系
决定时机 编译时 (静态绑定) 运行时 (动态绑定)
记住 参数不同 签名相同,子类特化

记住这个简单的类比:

  • 重载就像一个工具箱里的多个不同功能的螺丝刀(十字、一字、内六角),它们都叫“螺丝刀”,但功能不同,根据你的需求(参数)选择哪个。
  • 重写就像儿子继承父亲的手艺,父亲会“做菜”,儿子也会“做菜”,但儿子会做一道“宫保鸡丁”,这是他自己独特的做法(实现),而不是简单地沿用父亲的做法。
分享:
扫描分享到社交APP
上一篇
下一篇