为什么这段代码中有Unhandled Exception?

Why there is Unhandled Exception in this code?

我遇到了以下代码:

class Animal{
    public void eat() throws Exception {}
}

class Dog extends Animal{
    public void eat(){} //no exception thrown
    public static void main(String[] args){
          Animal a = new Dog();
          Dog d = new Dog();
          d.eat();   //ok
          a.eat();  //does not compile!..(1)
    }
}

这里,(1) 不会编译,即使在运行时 Dog 的 eat() 方法将被调用。为什么会这样? Java支持这个的原因是什么?这不应该作为错误提交吗?

因为您正在使用 Animal 引用来引用 DogAnimal.eat 的签名包括 Exception。编译器知道 Dog 是一种 Animal,但是一旦您使用 Animal 引用,它直到运行时才知道它是 Dog

换句话说,所有 Dog(s) 都是 Animal(s) 但并非所有 Animal(s) 都是 Dog(s)。

编辑

你本可以添加演员

((Dog) a).eat();  //would compile

在运行时,如果 a 实际上不是 Dog,那将失败。

Animal a = new Dog();

OOP (Object Oriented Programming)中,这个叫做polymorphism。而在 Java 中(主要是在 OOP 支持语言中,例如 C#),这种行为是编译检查。这意味着编译器在 编译时 只知道 a 是动物,直到 运行时才能知道 a 是狗。

例如:

Animal a = new Dog();
a.bark(); // cannot. because compiler doesn't know a is a dog until runtime
((Dog)a).bark(); // yes. we say to compiler: a **must** be a dog

另一个例子是:

    Animal a = new Cat();
    // yes. can compile. we force compiler to know this animal is a dog. 
    //but will run-time exception because in fact this is a cat
    ((Dog)a).bark(); 

希望对您有所帮助:)

首先你没有遵守方法覆盖的规则。如果 Base class 方法抛出任何异常,则子 class 方法必须抛出相等或低级异常。现在这段代码可以正常工作,因为它遵循方法覆盖规则。另外@Elliot 说的是对的,编译器在编译时不知道 dog 对象(正如 Animal 所指的)。它只会在 运行 时间解决。

class Animal{
public void eat() throws Exception {}
}

class Test extends Animal{
  public void eat()throws Exception{} 
  public static void main(String[] args)throws Exception{
      Animal a = new Test();
      Test d = new Test();
      d.eat();
      a.eat();  
}
}