Java 方法覆盖

子类可以覆盖从父类继承的方法。在本教程中,我们将通过示例了解 Java 中的方法覆盖。

在本教程中,我们将通过示例了解 Java 中的方法覆盖。

Java 方法覆盖

在上一个教程中,我们学习了继承。继承是一个 OOP 属性,它允许我们从现有类(父类)派生一个新类(子类)。子类继承父类的属性和方法。

现在,如果在子类都定义了和父类相同的方法,那么子类的方法会覆盖父类的方法。这称为方法覆盖。

示例 1:方法覆盖

public class Animal {
   public void displayInfo() {
      System.out.println("I am an animal.");
   }
}

public class Dog extends Animal {
   @Override
   public void displayInfo() {
      System.out.println("I am a dog.");
   }
}

public class Main {
   public static void main(String[] args) {
      Dog d1 = new Dog();
      d1.displayInfo();
   }
}

输出

I am a dog.

在上面的程序中,父类 Animal 和子类 Dog 都定义了 displayInfo() 方法。

从程序运行的结果看出,当我们使用子类对象 d1 调用 displayInfo() 方法时,执行的是定义在子类总的方法,并没有调用父类的方法。这是因为子类覆盖了父类的同名方法。

Java 中方法覆盖的工作。
Java 中的方法覆盖

请注意我们示例中使用了 @Override 注释。在 Java 中,我们用注解向编译器提供信息。这里, @Override 注解告诉编译器此方法覆盖了父类的方法。

当覆盖父类的方法是,注解 @Override 不是必须的。 但是,一旦我们使用了这个注解,该方法应遵循所有覆盖规则。否则,编译器会产生错误。

方法覆盖的规则

  • 覆盖的方法必须具有相同的方法名称、相同的返回类型和相同的参数列表。
  • 声明为 finalstatic 的方法不能被覆盖。
  • 必须覆盖父类的抽象方法

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.");
   }
}

public class Main {
   public static void main(String[] args) {
      Dog d1 = new Dog();
      d1.displayInfo();
   }
}

输出

I am an animal.
I am a dog.

在上面的例子中,子类 Dog 覆盖了父类 AnimaldisplayInfo() 方法。

在子类的 displayInfo() 方法种,我们使用 super.displayInfo() 调用了父类 AnimaldisplayInfo() 方法。

需要注意的是,Java 中的构造函数不是继承的。因此,Java 中没有构造函数覆盖这样的东西。

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

方法覆盖中的访问修饰符

子类在覆盖父类方法的时候,子类方法可以具有和父类的方法不同的访问修饰符。但是,有一个限制:子类方法的访问权限不能小于父类方法的访问权限。

例如:

假设父类声明了一个 protected 方法,子类中的相同方法可以是 publicprotected ,但不能是 private

示例 3:覆盖中的访问修饰符

public class Animal {
   protected void displayInfo() {
      System.out.println("I am an animal.");
   }
}

public class Dog extends Animal {
   public void displayInfo() {
      System.out.println("I am a dog.");
   }
}

public class Main {
   public static void main(String[] args) {
      Dog d1 = new Dog();
      d1.displayInfo();
   }
}

输出

I am a dog.

如果子类覆盖方法使用了比父类方法更小访问权限的修饰符,则会编译报错:

public class Dog extends Animal {
   private void displayInfo() {
      System.out.println("I am a dog.");
   }
}

上例中子类 DogdisplayInfo() 的访问权限 private 小于父类方法的 protected,编译程序的时候,给出如下错误:

java: net.gobeta.Dog中的displayInfo()无法覆盖net.gobeta.Animal中的displayInfo()
  正在尝试分配更低的访问权限; 以前为public

覆盖抽象方法

在 Java 中,抽象类作为其他类的父类创建,抽象类是不能实例化的。子类继承抽象类后,必须实现抽象类中的抽象方法。

我们将在后面的教程中了解更多关于抽象类和抽象方法的覆盖。