目录
1. 方法重载 (Overload)
什么是方法重载?
重载的特点:
重载的示例:
重载的调用:
2. 方法重写 (Override)
什么是方法重写?
重写的特点:
重写的示例:
重写的调用:
3. 重写 vs 重载 对比表
4. 特殊情况和注意事项
静态方法
私有方法
final 方法
构造方法
5. 实际应用建议
总结
在 Java 面向对象编程中,方法重写和方法重载是两个重要但容易混淆的概念。它们都涉及到方法的定义,但有着本质的区别。
1. 方法重载 (Overload)
什么是方法重载?
方法重载是指在同一个类中,允许存在多个同名方法,但这些方法的参数列表必须不同(参数类型、参数个数或参数顺序不同)。
重载的特点:
- 发生在同一个类中
- 方法名必须相同
- 参数列表必须不同(类型、个数、顺序)
- 返回类型可以相同也可以不同
- 访问修饰符可以不同
- 可以抛出不同的异常
重载的示例:
public class Calculator {// 方法1:两个整数相加public int add(int a, int b) {return a + b;}// 方法2:三个整数相加 - 参数个数不同public int add(int a, int b, int c) {return a + b + c;}// 方法3:两个浮点数相加 - 参数类型不同public double add(double a, double b) {return a + b;}// 方法4:整数和浮点数相加 - 参数顺序不同(虽然这里效果类似)public double add(int a, double b) {return a + b;}// 方法5:浮点数和整数相加 - 参数顺序不同public double add(double a, int b) {return a + b;}
}
重载的调用:
编译器根据方法签名(方法名 + 参数列表)来决定调用哪个重载方法。
Calculator calc = new Calculator();
calc.add(1, 2); // 调用 add(int, int)
calc.add(1, 2, 3); // 调用 add(int, int, int)
calc.add(1.5, 2.5); // 调用 add(double, double)
2. 方法重写 (Override)
什么是方法重写?
方法重写是指子类重新定义父类中已有的方法,提供特定的实现。重写的方法必须与父类方法有相同的方法签名和返回类型(或是其子类)。
重写的特点:
- 发生在继承关系的父子类之间
- 方法名必须相同
- 参数列表必须完全相同
- 返回类型必须相同或是其子类(协变返回类型)
- 访问修饰符不能比父类更严格
- 不能抛出比父类方法更宽泛的检查异常
重写的示例:
// 父类
class Animal {public void makeSound() {System.out.println("动物发出声音");}public Animal getAnimal() {return new Animal();}
}// 子类
class Dog extends Animal {// 重写 makeSound 方法@Overridepublic void makeSound() {System.out.println("汪汪汪");}// 协变返回类型 - 返回 Dog 类型(Animal 的子类)@Overridepublic Dog getAnimal() {return new Dog();}
}// 另一个子类
class Cat extends Animal {@Overridepublic void makeSound() {System.out.println("喵喵喵");}
}
重写的调用:
运行时根据对象的实际类型来决定调用哪个方法(多态的体现)。
Animal myAnimal = new Animal();
Animal myDog = new Dog();
Animal myCat = new Cat();myAnimal.makeSound(); // 输出: 动物发出声音
myDog.makeSound(); // 输出: 汪汪汪 (多态)
myCat.makeSound(); // 输出: 喵喵喵 (多态)
3. 重写 vs 重载 对比表
特性 | 方法重载 (Overload) | 方法重写 (Override) |
发生位置 | 同一个类中 | 继承关系的父子类之间 |
方法名 | 必须相同 | 必须相同 |
参数列表 | 必须不同 | 必须完全相同 |
返回类型 | 可以不同 | 必须相同或是其子类 |
访问修饰符 | 可以不同 | 不能比父类更严格 |
异常抛出 | 可以不同 | 不能抛出更宽泛的检查异常 |
调用时机 | 编译时决定 | 运行时决定(多态) |
目的 | 提高方法灵活性 | 实现多态,定制子类行为 |
注解 | 可选使用 | 建议使用 |
4. 特殊情况和注意事项
静态方法
静态方法可以被"重载",但不能被"重写"。如果子类定义了与父类相同的静态方法,这称为方法隐藏(Method Hiding),不是重写。
class Parent {static void staticMethod() {System.out.println("Parent static method");}
}class Child extends Parent {static void staticMethod() { // 这是隐藏,不是重写System.out.println("Child static method");}
}
私有方法
私有方法不能被重写,因为它们在子类中不可见。私有方法可以被重载。
final 方法
final 方法不能被重写,但可以被重载。
构造方法
构造方法可以被重载(在同一个类中),但不能被重写(因为构造方法不能继承)。
5. 实际应用建议
- 使用 @Override 注解:在重写方法时加上
@Override
注解,让编译器帮助检查是否正确重写 - 遵守里氏替换原则:子类重写的方法不应该改变父类方法的预期行为
- 谨慎重写:不要随意重写核心方法,特别是
equals()
,hashCode()
,toString()
等方法 - 文档注释:为重写方法添加适当的文档注释,说明与父类方法的区别
总结
方法重载和重写是 Java 多态性的两种不同表现形式:
- 重载是编译时多态,通过不同的参数列表提供方法的不同版本
- 重写是运行时多态,通过子类定制父类行为来实现真正的多态
理解它们的区别对于编写良好的面向对象代码至关重要。记住这个简单的口诀:重载同类不同参,重写异类同参不同实现。