Java 方法在子类重写的父类中引发异常

Java 方法在子类重写的父类中引发异常,java,Java,如果实例方法被子类重写,为什么引用到父类的子类实例需要捕获异常。 这是一张清晰的图片 public class Animal{ public void printName() throws Exception{ System.out.println("Animal Method"); } } public class Dog extends Animal{ public void printName(){ System.out.println("Dog Meth

如果实例方法被子类重写,为什么引用到父类的子类实例需要捕获异常。 这是一张清晰的图片

public class Animal{
  public void printName() throws Exception{
   System.out.println("Animal Method");
  }
}


public class Dog extends Animal{

  public void printName(){
     System.out.println("Dog Method");
  }
  public static void main(String[] args){

    Animal m = new Dog();
    ((Dog)m).printName(); //prints Dog Method
    m.printName(); // this is supposed to be overridden and will print "Dog Method", why the throws Exception of Animal method printName was copied. to the instance

  }
}

变量
m
的引用类型是Animal,因此在编译时,使用类Animal的方法签名,尽管在运行代码时,实际调用的方法是子类中的方法。

变量
m
的引用类型是Animal,因此在编译时,使用类Animal的方法签名,但在运行代码时,实际调用的方法是子类中的方法。

这是因为变量m被定义为Animal,编译器看到Animal的printName方法抛出异常

您可能知道可以调用变量的方法是由其类型、编译时类型声明定义的,如:

Animal m;
即使m实际上指向一只狗,你也只能在m上调用Animal的方法。(除非你投)

同样,它可能抛出的异常也由其声明的类型定义。这就是为什么在对Dog声明的对象调用该方法时,不需要捕获异常


真正有趣的是,派生类中的重写方法只能从throws子句中删除异常,或者使它们更具体,但不能添加任何异常,因为这会导致对基类调用方法的人产生令人惊讶的结果。

这是因为变量m被定义为动物,编译器看到动物的printName方法抛出异常

您可能知道可以调用变量的方法是由其类型、编译时类型声明定义的,如:

Animal m;
即使m实际上指向一只狗,你也只能在m上调用Animal的方法。(除非你投)

同样,它可能抛出的异常也由其声明的类型定义。这就是为什么在对Dog声明的对象调用该方法时,不需要捕获异常


真正有趣的是,派生类中的重写方法只能从throws子句中删除异常,或者使它们更具体,但不能添加任何异常,因为这将导致对基类调用方法的人产生令人惊讶的结果。

在编译时,
m
实际上是
Animal
类型,所以您应该捕获异常,因为异常被检查,并且编译时没有dog对象,但在运行时,m是
dog
类型。因此将调用dog
printName
方法,但在这一行中,
((dog)m).printName()
将其强制转换为
dog
,因此不需要捕获异常。

在编译时,
m
实际上是
动物类型,因此,您应该捕获异常,因为检查了异常,并且编译时没有dog对象,但在运行时,m是
dog
类型。因此将调用dog
printName
方法,但在这一行中,
((dog)m).printName()
将其强制转换为
dog
,因此无需捕获异常