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()
方法时,执行的是定义在子类总的方法,并没有调用父类的方法。这是因为子类覆盖了父类的同名方法。
请注意我们示例中使用了 @Override
注释。在 Java 中,我们用注解向编译器提供信息。这里, @Override
注解告诉编译器此方法覆盖了父类的方法。
当覆盖父类的方法是,注解 @Override
不是必须的。 但是,一旦我们使用了这个注解,该方法应遵循所有覆盖规则。否则,编译器会产生错误。
方法覆盖的规则
- 覆盖的方法必须具有相同的方法名称、相同的返回类型和相同的参数列表。
- 声明为
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.");
}
}
public 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()
方法。
在子类的 displayInfo()
方法种,我们使用 super.displayInfo()
调用了父类 Animal
的
displayInfo()
方法。
需要注意的是,Java 中的构造函数不是继承的。因此,Java 中没有构造函数覆盖这样的东西。
但是,我们可以使用 super()
从其子类调用父类的构造函数。要了解更多信息,请访问Java super 关键字。
方法覆盖中的访问修饰符
子类在覆盖父类方法的时候,子类方法可以具有和父类的方法不同的访问修饰符。但是,有一个限制:子类方法的访问权限不能小于父类方法的访问权限。
例如:
假设父类声明了一个 protected
方法,子类中的相同方法可以是 public
或 protected
,但不能是 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.");
}
}
上例中子类 Dog
的 displayInfo()
的访问权限 private
小于父类方法的 protected
,编译程序的时候,给出如下错误:
java: net.gobeta.Dog中的displayInfo()无法覆盖net.gobeta.Animal中的displayInfo()
正在尝试分配更低的访问权限; 以前为public
覆盖抽象方法
在 Java 中,抽象类作为其他类的父类创建,抽象类是不能实例化的。子类继承抽象类后,必须实现抽象类中的抽象方法。
我们将在后面的教程中了解更多关于抽象类和抽象方法的覆盖。