原文: https://www.programiz.com/java-programming/method-overriding

在本教程中,我们将借助示例学习 Java 中的方法覆盖。

在上一教程中,我们了解了继承。 继承是一个 OOP 属性,它使我们可以从现有的类(超类)派生一个新的类(子类)。 子类继承超类的属性和方法。

现在,如果在超类类和子类类中都定义了相同的方法,则子类类的方法将覆盖超类的方法。 这称为方法覆盖。


示例 1:方法覆盖

  1. class Animal {
  2. public void displayInfo() {
  3. System.out.println("I am an animal.");
  4. }
  5. }
  6. class Dog extends Animal {
  7. @Override
  8. public void displayInfo() {
  9. System.out.println("I am a dog.");
  10. }
  11. }
  12. class Main {
  13. public static void main(String[] args) {
  14. Dog d1 = new Dog();
  15. d1.displayInfo();
  16. }
  17. }

输出

  1. I am a dog.

在上述程序中,Animal超类和Dog子类中都存在displayInfo()方法。

当我们使用d1对象(子类的对象)调用displayInfo()时,将调用子类Dog内部的方法。 子类的displayInfo()方法将覆盖超类的相同方法。

Java 方法覆盖 - 图1

注意在我们的示例中使用了@Override注解。 在 Java 中,注解是我们用来向编译器提供信息的元数据。 在此,@Override注解指定编译器,该注解之后的方法将覆盖超类的方法。

使用@Override不是强制性的。 但是,当我们使用此方法时,该方法应遵循所有覆盖规则。 否则,编译器将生成错误。


Java 覆盖规则

  • 父类和子类都必须具有相同的方法名称,相同的返回类型和相同的参数列表。
  • 我们不能覆盖声明为finalstatic的方法。
  • 我们应该始终覆盖超类的抽象方法(将在以后的教程中进行讨论)。

Java 覆盖中的super关键字

在 Java 中执行覆盖时出现的一个常见问题是:

覆盖后可以访问超类的方法吗?

好吧,答案是。 要从子类访问超类的方法,我们使用super关键字。

示例 2:使用super关键字

  1. class Animal {
  2. public void displayInfo() {
  3. System.out.println("I am an animal.");
  4. }
  5. }
  6. class Dog extends Animal {
  7. public void displayInfo() {
  8. super.displayInfo();
  9. System.out.println("I am a dog.");
  10. }
  11. }
  12. class Main {
  13. public static void main(String[] args) {
  14. Dog d1 = new Dog();
  15. d1.displayInfo();
  16. }
  17. }

输出

  1. I am an animal.
  2. I am a dog.

在上面的示例中,子类Dog覆盖了超类Animal的方法displayInfo()

当我们使用Dog子类的d1对象调用方法displayInfo()时,将调用Dog子类内部的方法; 不会调用超类内部的方法。

Dog子类的displayInfo()内部,我们使用super.displayInfo()调用超类的displayInfo()


重要的是要注意,Java 中的构造器不会被继承。 因此,在 Java 中不存在构造器覆盖这样的事情。

但是,我们可以从其子类中调用超类的构造器。 为此,我们使用super()。 要了解更多信息,请访问 Java super关键字


方法覆盖中的访问说明符

在超类及其子类中声明的相同方法可以具有不同的访问说明符。 但是,有一个限制。

我们只能在提供比超类的访问说明符更大的访问权限的子类中使用那些访问说明符。 例如,

假设将超类中的方法myClass()声明为protected。 然后,子类中的相同方法myClass()可以是publicprotected,但不能是private

示例 3:覆盖中的访问说明符

  1. class Animal {
  2. protected void displayInfo() {
  3. System.out.println("I am an animal.");
  4. }
  5. }
  6. class Dog extends Animal {
  7. public void displayInfo() {
  8. System.out.println("I am a dog.");
  9. }
  10. }
  11. class Main {
  12. public static void main(String[] args) {
  13. Dog d1 = new Dog();
  14. d1.displayInfo();
  15. }
  16. }

输出

  1. I am a dog.

In the above example, the subclass Dog overrides the method displayInfo() of the superclass Animal.

每当我们使用d1(子类的对象)调用displayInfo()时,就会调用子类内部的方法。

请注意,在Animal超类中将displayInfo()声明为protected。 相同的方法在Dog子类中具有public访问说明符。 这是可能的,因为public提供的访问权限大于protected


覆盖抽象方法

在 Java 中,抽象类被创建为其他类的超类。 并且,如果类包含抽象方法,则必须覆盖它。

在后面的教程中,我们将学习有关抽象类和抽象方法的覆盖的更多信息。