在上一个教程中,我们学习了继承。继承是OOP的一个属性,它允许我们从现有类(超类)派生出一个新类(子类)。子类继承超类的属性和方法。
现在,如果同一个方法在超类和子类中都被定义了,那么子类中的方法就会覆盖超类中的方法。这被称为方法重写。
示例 1:方法重写
class Animal {
public void displayInfo() {
System.out.println("I am an animal.");
}
}
class Dog extends Animal {
@Override
public void displayInfo() {
System.out.println("I am a dog.");
}
}
class Main {
public static void main(String[] args) {
Dog d1 = new Dog();
d1.displayInfo();
}
}
输出:
I am a dog.
在上面的程序中,displayInfo()
方法同时存在于Animal超类和Dog子类中。
当我们使用d1对象(子类的对象)调用displayInfo()
时,会调用子类Dog中的方法。子类的displayInfo()
方法会覆盖超类中同名的方法。

请注意我们在示例中使用了@Override
注解。在Java中,注解是我们提供给编译器的元数据。这里,@Override
注解指定编译器,该注解后面的方法重写了超类中的方法。
使用@Override
不是强制性的。但是,当我们使用它时,方法必须遵循所有重写规则。否则,编译器将生成错误。
Java 方法重写规则
- 超类和子类必须具有相同的方法名、相同的返回类型和相同的参数列表。
- 我们不能重写声明为
final
和static
的方法。 - 我们应该始终重写超类的抽象方法(将在后续教程中讨论)。
Java 方法重写中的 super 关键字
在Java中执行重写时,一个常见的问题是:
重写后是否可以访问超类中的方法?
答案是是的。要从子类访问超类的方法,我们使用super
关键字。
示例 2:super 关键字的使用
class Animal {
public void displayInfo() {
System.out.println("I am an animal.");
}
}
class Dog extends Animal {
public void displayInfo() {
super.displayInfo();
System.out.println("I am a dog.");
}
}
class Main {
public static void main(String[] args) {
Dog d1 = new Dog();
d1.displayInfo();
}
}
输出:
I am an animal. I am a dog.
在上面的示例中,子类Dog重写了超类Animal的displayInfo()
方法。
当我们使用Dog子类的d1对象调用displayInfo()
方法时,会调用Dog子类中的方法;而不会调用超类中的方法。
在Dog子类的displayInfo()
方法内部,我们使用了super.displayInfo()
来调用超类的displayInfo()
。
需要注意的是,Java中的构造函数不会被继承。因此,Java中不存在构造函数重写一说。
但是,我们可以从子类调用超类的构造函数。为此,我们使用super()
。要了解更多,请访问Java super关键字。
方法重写中的访问修饰符
超类及其子类中声明的相同方法可以具有不同的访问修饰符。但是,有一个限制。
在子类中,我们只能使用那些比超类访问修饰符提供更大访问权限的访问修饰符。例如,
假设超类中的一个方法myClass()
被声明为protected
。那么,子类中同名的方法myClass()
可以被声明为public
或protected
,但不能是private
。
示例 3:重写中的访问修饰符
class Animal {
protected void displayInfo() {
System.out.println("I am an animal.");
}
}
class Dog extends Animal {
public void displayInfo() {
System.out.println("I am a dog.");
}
}
class Main {
public static void main(String[] args) {
Dog d1 = new Dog();
d1.displayInfo();
}
}
输出:
I am a dog.
在上面的示例中,子类Dog重写了超类Animal的displayInfo()
方法。
每当我们使用d1(子类对象)调用displayInfo()
时,都会调用子类中的方法。
请注意,displayInfo()
在Animal超类中被声明为protected
。在Dog子类中,相同的方法具有public
访问修饰符。这是可能的,因为public
比protected
提供了更大的访问权限。
重写抽象方法
在Java中,抽象类是为了成为其他类的超类而创建的。如果一个类包含抽象方法,那么必须重写它。
我们将在后续教程中了解更多关于抽象类和抽象方法重写的内容。
另请阅读