2017-01-24 99 views
14

閱讀Why can't overriding methods throw exceptions後,我明白,如果方法聲明爲拋出一個經過檢查的異常,在子類中重寫方法只能聲明拋出該異常或它的子類:調用重寫方法拋出經過檢查的異常

class A { 
    public void foo() throws IOException {..} 
} 

class B extends A { 
    @Override 
    public void foo() throws SocketException {..} // allowed 

    @Override 
    public void foo() throws SQLException {..} // NOT allowed 
} 

所以,因爲SocketException IS-A IOException我可以聲明重寫方法作爲拋出IOException的任何子類。

在我的程序中,我想調用聲明爲throws FileNotFoundException IS-A IOException的覆蓋方法。也有try-catch塊

import java.io.*; 
class Sub extends Super{ 
    public static void main (String [] args){ 
     Super p = new Sub(); 
     try { 
      p.doStuff(); 
     }catch(FileNotFoundException e){ 

     } 
    } 
    public void doStuff() throws FileNotFoundException{} 
} 

class Super{ 
    public void doStuff() throws IOException{} 
} 

處理,但我得到的是編譯時錯誤: Screenshot

Sub.java:6: error: unreported exception IOException; must be caught or declared to be thrown 
        p.doStuff(); 
          ^

是什麼原因呢?我有點困惑,因爲Base類的所有東西都可用於子類。

此外更令人困惑的是能否趕上ExceptionThrowable除了IOException(與Overriding概念相反)。

+3

有些人可能會阻止圖像。你也可以在你的問題中複製粘貼編譯錯誤。 – CKing

+2

@CKing現在加入 – Pauwelyn

回答

10

What is the reason for that? I'm a little confused because everything that the Base class has also available to the subclasses.

你需要捕捉的IOException而不是FilenotFoundException。這是因爲儘管子類中的doStuff方法在運行時會被調用,但編譯器還不知道。它只知道超類中的doStuff方法,它聲明它爲throwsIOException

要解決您的編輯問題:catch塊可以選擇捕獲try塊中預期的確切異常,或者可以選擇捕獲異常的超類。背後的推理與方法重寫沒有任何關係。

2

這是因爲您正在使用靜態類型Super的對象。 編譯器不能知道在運行時p指向一個Sub對象,所以它想要捕獲超類中聲明的方法拋出的異常

14

您的對象引用類型爲Super,即使您知道它是運行時的Sub對象。因此,編譯器正在檢查Super的方法定義並給你這個編譯錯誤。

這將是從得到以下編譯器錯誤沒有什麼不同:

Object o = new String("Hello World"); 
o.charAt(2); //Obviously not allowed 

重要的是要記住,throws條款是方法定義的一部分是很重要的。

+1

但是,java.lang.Object沒有'charAt'方法雖然'Super'和'Sub'都有 – Pauwelyn

+2

同意。然而,主體完全一樣,編譯器只檢查你調用的方法是否在引用類型上(在我的例子中是'Object',在你的情況下''Super'')。 – StuPointerException

2

因爲它通過聲明類型進行檢查,在此例中爲Super

不知道(或選中)您的p將僅包含Sub的實例。另外,定義一個超類變量並僅將其用於1個特定的子類是沒有意義的。

因此,您的Super p包含Super.class的實例。其方法doStuff()可以拋出延伸IOException的一切,可以說UnsupportedEncodingException,但您只嘗試捕獲FileNotFoundException,以致Unsupported...可能已被拋出並且必須處理。

5

編譯器不考慮對象的類型,但是您使用的引用類型是Super

作爲Super.doStuff() throws IOException,這是你必須捕捉的。

順便說一句,我強烈建議使用IDE,你會發現它更高效。

+0

除了IOException之外,我怎麼也可以使用'Exception'和'Throwable'? 這與Overriding相反,只能聲明拋出該異常或其子類 – Pauwelyn

+0

@Pau重寫的方法不能拋出這些但你可以捕獲它們 –

3

通過聲明數p作爲超級

Super p = ... 

你的編譯器只知道p是某種SuperSuperdoStuff()會拋出一個IOException,但您的代碼僅捕獲IOExceptionFileNotFoundException的特例。如果你想告訴你的編譯器,這只是一個Sub而不是一個Super只是宣佈pSub

在這種情況下,它不明確聲明爲SubSuper所以任何Super或其童車可能發生,並拋出這可能不是一個FileNotFoundException或任何它的任何IOException的孩子的。