2016-08-23 87 views
2

下面的代码不会因为未处理的异常的编译,但它似乎对我来说,应该没有问题:为什么这被认为是一个未处理的异常?

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

public class Sedan extends Car { 
    public void drive() { 
     System.out.println("Driving Sedan..."); 
    } 
    public static void main(String[] args) { 
     Car c = new Sedan(); 
     c.drive(); //unhandled exception! 
    } 
} 

它不应该是明显的编译器,当覆盖方法c.drive()是称为,检查异常不会被抛出?为什么仅仅因为引用的类型是Car而不是Sedan类型,我们必须将驱动器视为仍然抛出检查的异常?首要的方法不是!

+0

'drive'可以抛出'Exception'但'主要修复'不处理它。 – tkausl

+3

,因为'c'可能不是'Sedan',它可以抛出一个'Exception'。由于'throw'在'Car'中定义,所以您需要处理它。 – SomeJavaGuy

+0

做'Sedan c = new Sedan();' –

回答

5

不幸的是,不,对编译器来说并不明显。

编译器本质上是看Car c和调用drive。编译器不知道c指向的对象的运行时类型。因此,它会评估Car.drive()的方法签名,其中包括throws Exception

为了使它更清晰,如果在某些其他方法c被重新分配给一些仍然引发此异常的对象SUV?在调用drive方法时,编译器无法知道对象的状态。

+0

其实,如果我们有'最后的汽车c',类型推断是可能的。但是这并没有发生,因为这种语言是建立在静态打字的基础上的。 – dhke

+0

@dhke因为我们也有“有效的最终”的概念,所以这种明确的标记不是必需的。但这会令人困惑。 – biziclop

+0

@dhke通过类型推断,您可以使用'val c = new Sedan()',然后它可以用于显而易见的原因。如果你明确地声明类型为'Car',那么就是你所得到的。 –

0

您可以

Sedan c = new Sedan(); 
c.drive(); 

2.

Car c = new Sedan(); 
((Sedan) c).drive(); 
相关问题