2016-08-23 82 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(); 
相關問題