需要澄清继承和例外

时间:2012-07-12 19:47:08

标签: java oop

所以我想弄清楚为什么一个程序正在编译它的方式,希望你们能为我解释一下。

class Vehicle{
   public void drive() throws Exception{
     System.out.println("Vehicle running");
   }
}

class Car extends Vehicle{
   public void drive(){
      System.out.println("Car Running");
   }

   public static void main(String[] args){
      Vehicle v = new Car();
      Car c = new Car();
      Vehicle c2 = (Vehicle) v;

      c.drive();
      try {
          v.drive();
      } catch (Exception e) {
          e.printStackTrace();
      } //try v.drive()

      try {
          c2.drive();
      } catch (Exception e) {
          e.printStackTrace();
      } //try c2.drive()
   }
}

因此上述程序的输出将是

汽车行驶
汽车运行
汽车行驶

我的问题是,为什么我必须执行try / catch块来为v和c2对象调用drive()方法而不是c?他们都是Car的例子,所以这里发生了什么?

4 个答案:

答案 0 :(得分:10)

Vehicle有一个drive()方法会引发异常。

Car使用自己的Vehicle方法覆盖Drive()的{​​{1}}方法,该方法不会引发异常。

你得到输出的原因是因为即使Drive()是car类型,编译器在编译时也不知道这个事实,所以当你调用Vehicle v时编译器没有我知道你正在调用Car的v.drive()方法。

假设您以下列方式实例化drive

v

编译时,你不知道v是否是汽车。在你运行程序之前你不会知道。

答案 1 :(得分:1)

重写方法可以更具体地说明它们返回和抛出的内容。它们可以使用返回对象和异常的子类,或者省略在父方法签名中声明的异常。当你调用((Vehicle)new Car())。drive()然后执行子程序的实现,但父进程的方法签名在编译时被使用,这会强制你捕获在Vehicle中定义的异常。

答案 2 :(得分:0)

我们有:

  Vehicle v = new Car();
  Car c = new Car();
  Vehicle c2 = (Vehicle) v;

此时,vc2Vehicle。这意味着您正在调用public void drive() throws Exception Vehicle。这就是为什么你需要对这些方法使用try / catch而不是c.drive()的原因(因为该方法不会抛出异常)。

答案 3 :(得分:0)

其他答案解释了过度使用的方法;然而,还有另一个问题。你这么说:

  

他们都是Car的例子,所以这里发生了什么?

但是对于编译器来说,它们并不是Car的所有实例 - 编译器会查看变量的类型

  Vehicle v = new Car();
  Car c = new Car();
  Vehicle c2 = (Vehicle) v;

在编译时,v被视为Vehiclec被视为Car,异常将被相应处理。在运行时,JVM知道v实际上包含Car,但那是不同的。