我遇到了以下代码:
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支持这个的原因是什么?这不应该是一个错误吗?
答案 0 :(得分:7)
因为您使用Animal
引用来引用Dog
。 Animal.eat
的签名包含Exception
。编译器知道Dog
是一种Animal
,但是一旦使用Animal
引用,它就不知道它是Dog
直到运行时。
换句话说,所有Dog
(s)都是Animal
(s),但并非所有Animal
都是Dog
(s)。
修改强>
您可以添加演员
((Dog) a).eat(); //would compile
在运行时,如果a
实际上不是Dog
,则会失败。
答案 1 :(得分:3)
Animal a = new Dog();
OOP (Object Oriented Programming)
中的,称为polymorphism
。在Java中(主要是在OOP支持语言中,如C#),这种行为是编译检查。这意味着编译时的编译器只知道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();
希望这有帮助:)
答案 2 :(得分:3)
首先,您没有遵循方法覆盖的规则。如果Base类方法抛出任何Exception,那么子类方法必须抛出相等或低级异常。现在这个代码将正常工作,因为它遵循覆盖规则的方法。另外@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();
}
}