Java - 覆盖
在上一章中,我们讨论了超类和子类。如果一个类从它的超类继承了一个方法,那么如果它没有被标记为final,那么就有机会覆盖这个方法。
重写的好处是:能够定义特定于子类类型的行为,这意味着子类可以根据其要求实现父类方法。
在面向对象的术语中,覆盖意味着覆盖现有方法的功能。
示例
让我们看一个例子。
现场演示class Animal { public void move() { System.out.println("Animals can move"); } } class Dog extends Animal { public void move() { System.out.println("Dogs can walk and run"); } } public class TestDog { public static void main(String args[]) { Animal a = new Animal(); // Animal reference and object Animal b = new Dog(); // Animal reference but Dog object a.move(); // runs the method in Animal class b.move(); // runs the method in Dog class } }
这将产生以下结果 -
输出
Animals can move Dogs can walk and run
在上面的例子中,你可以看到即使 b 是 Animal 的一种类型,它在 Dog 类中运行 move 方法。这样做的原因是:在编译时,对引用类型进行检查。但是,在运行时,JVM 会确定对象类型并运行属于该特定对象的方法。
因此,在上面的示例中,由于 Animal 类具有 move 方法,因此程序将正确编译。然后,在运行时,它运行特定于该对象的方法。
考虑以下示例 -
示例
现场演示class Animal { public void move() { System.out.println("Animals can move"); } } class Dog extends Animal { public void move() { System.out.println("Dogs can walk and run"); } public void bark() { System.out.println("Dogs can bark"); } } public class TestDog { public static void main(String args[]) { Animal a = new Animal(); // Animal reference and object Animal b = new Dog(); // Animal reference but Dog object a.move(); // runs the method in Animal class b.move(); // runs the method in Dog class b.bark(); } }
这将产生以下结果 -
输出
TestDog.java:26: error: cannot find symbol b.bark(); ^ symbol: method bark() location: variable b of type Animal 1 error
这个程序会抛出编译时错误,因为 b 的引用类型 Animal 没有名为 bark 的方法。
方法覆盖的规则
-
参数列表应与被覆盖方法的参数列表完全相同。
-
返回类型应与父类中原始重写方法中声明的返回类型相同或子类型。
-
访问级别不能比被覆盖方法的访问级别更严格。例如:如果超类方法声明为public,那么子类中的覆盖方法不能是private或protected。
-
实例方法只有被子类继承才能被覆盖。
-
声明为 final 的方法不能被覆盖。
-
声明为静态的方法不能被覆盖,但可以重新声明。
-
如果一个方法不能被继承,那么它就不能被覆盖。
-
与实例的超类在同一包中的子类可以覆盖任何未声明为私有或最终的超类方法。
-
不同包中的子类只能覆盖声明为public或protected的非final方法。
-
覆盖方法可以抛出任何未检查的异常,无论被覆盖的方法是否抛出异常。但是,覆盖方法不应抛出新的或比被覆盖方法声明的异常更广泛的检查异常。重写方法可以抛出比重写方法更窄或更少的异常。
-
构造函数不能被覆盖。
使用 super 关键字
当调用重写方法的超类版本时,super 使用了关键字。
示例
现场演示class Animal { public void move() { System.out.println("Animals can move"); } } class Dog extends Animal { public void move() { super.move(); // invokes the super class method System.out.println("Dogs can walk and run"); } } public class TestDog { public static void main(String args[]) { Animal b = new Dog(); // Animal reference but Dog object b.move(); // runs the method in Dog class } }
这将产生以下结果 -
输出
Animals can move Dogs can walk and run
java
- Java 运算符
- Java 接口
- Java try-with-resources
- Java 注释
- Java 中的 String Length() 方法:如何通过示例查找
- Java String indexOf() 方法与子字符串和示例
- Java String charAt() 方法及示例
- Java String compareTo() 方法:如何与示例一起使用
- Java String contains() 方法 |用示例检查子字符串
- Java String endsWith() 方法及示例
- Java String replace()、replaceAll() 和 replaceFirst() 方法
- Java 中的静态变量:什么是静态块和方法 [示例]