Java 继承、重写与重载
继承是面向对象编程的基石之一,它允许我们创建分层的类结构,实现代码重用。与继承紧密相关的是方法重写(Overriding),而另一个容易混淆的概念是方法重载(Overloading)。本章将详细解释这三者的关系与区别。
继承 (Inheritance)
继承允许一个类(子类)获取另一个类(父类)的非私有属性和方法。子类可以像使用自己的成员一样使用父类的成员。
- 父类 (Superclass): 也叫基类,是被继承的类。
- 子类 (Subclass): 也叫派生类,是继承自父类的类。
在 Java 中,使用 extends 关键字实现继承。
java
// 父类
public class Vehicle {
String brand;
public void start() {
System.out.println("交通工具启动了!");
}
}
// 子类 Car 继承自 Vehicle
public class Car extends Vehicle {
String model;
public void honk() {
System.out.println("嘀嘀!汽车在鸣笛。");
}
}
// 使用
Car myCar = new Car();
myCar.brand = "Toyota"; // 访问从父类继承的属性
myCar.model = "Camry";
myCar.start(); // 调用从父类继承的方法
myCar.honk(); // 调用子类自己的方法super 关键字
super 关键字用于从子类中引用其直接父类的成员。
- 调用父类的构造方法:
super()必须是子类构造方法的第一行语句,用于调用父类的构造方法。 - 调用父类的方法:
super.methodName()可以用来调用被子类重写了的父类版本的方法。
java
public class Animal {
String name;
public Animal(String name) {
this.name = name;
System.out.println("Animal 的构造方法被调用");
}
public void eat() {
System.out.println(name + " 正在吃东西");
}
}
public class Dog extends Animal {
public Dog(String name) {
super(name); // 1. 调用父类的构造方法
System.out.println("Dog 的构造方法被调用");
}
@Override
public void eat() {
super.eat(); // 2. 调用父类的 eat() 方法
System.out.println(name + " 正在啃骨头");
}
}方法重写 (Method Overriding)
当子类不满意父类提供的某个方法的实现时,可以提供一个属于自己的、同名同参数的方法版本,这个过程就叫方法重写。
重写的规则:
- 方法名、参数列表必须与父类完全相同。
- 子类的返回类型必须与父类的返回类型相同或是其子类。
- 子类方法的访问修饰符不能比父类方法的更严格(例如,父类是
public,子类不能是protected)。 - 推荐使用
@Override注解,它可以让编译器检查这是否一个有效的重写。
java
class Shape {
public void draw() {
System.out.println("绘制一个形状");
}
}
class Circle extends Shape {
@Override // 告诉编译器,我要重写父类的方法
public void draw() {
System.out.println("绘制一个圆形 ○");
}
}方法重载 (Method Overloading)
方法重载是指在同一个类中,可以有多个同名的方法,只要它们的参数列表不同(参数的数量、类型或顺序不同)。重载与返回类型无关。
java
public class Printer {
public void print(String text) {
System.out.println(text);
}
// 重载 print 方法,接受不同类型的参数
public void print(int number) {
System.out.println(number);
}
// 重载 print 方法,接受不同数量的参数
public void print(String text, int times) {
for (int i = 0; i < times; i++) {
System.out.println(text);
}
}
}重写 (Overriding) vs. 重载 (Overloading)
这是 Java 中一个非常重要的对比,也是面试常见问题。
| 特性 | 方法重写 (Overriding) | 方法重载 (Overloading) |
|---|---|---|
| 目的 | 子类改变父类的行为 | 在一个类中提供多个同名但功能相似的方法 |
| 位置 | 发生在父类和子类之间 | 发生在同一个类中 |
| 方法签名 | 方法名和参数列表必须相同 | 方法名相同,但参数列表必须不同 |
| 返回类型 | 返回类型必须相同或是其子类 | 可以不同 |
| 多态性 | 体现了运行时的多态性 | 体现了编译时的多态性 |
| 关键字 | 涉及 extends 和 super | 无特定关键字 |
final 关键字的应用
final方法: 如果父类中的一个方法被声明为final,那么它不能被任何子类重写。javapublic class Parent { public final void lockMethod() { // ... } }final类: 如果一个类被声明为final,那么它不能被任何类继承。例如,Java 中的String类就是final的。javapublic final class Uninheritable { // ... }