Java 重写 Overriding

在上一章中,我们讨论了父类和子类。 如果一个类从它的父类继承了一个方法,那么只要它没有被标记为 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 b = new Dog(); 

      a.move();   
      b.move();   
   }
}

运行示例

编译执行上面的示例,结果如下

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 b = new Dog();

      a.move(); 
      b.move(); 
      b.bark();
   }
}

运行示例

上面示例编译执行结果如下

TestDog.java:24: 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();   // 调用父类的方法
      System.out.println("Dogs can walk and run");
   }
}

public class TestDog {

   public static void main(String args[]) {
      Animal b = new Dog(); 
      b.move(); 
   }
}

运行示例

上面示例编译执行结果如下

Animals can move
Dogs can walk and run

查看笔记

扫码一下
查看教程更方便