2011-04-26 68 views
3

我們正在努力實現某種形式的國際象棋遊戲中,我們定義了一個抽象類件與構造:的try-catch問題繼承(JAVA)

public Piece(String name) throws EmptyStringException{ 
    if(name.length()<=0) 
     throw new EmptyStringException(); 
    pieceName = name; 
} 

和延伸類看起來是這樣的:

public King(boolean white) throws EmptyStringException{   
    super("King", white);   
} 

「問題」在這裏,如果我想創建一個新的國王一塊,我必須寫:

try { 
    Piece king = new King(true); 
} catch(EmptyStringException e){ 
    e.printStackTrace(); 
} 

,而不是簡單得多:

Piece king = new King(true); 

所以,即使我根本不能創建EmptyStringException,我還是要嘗試/捕獲異常。

我該如何解決這個問題,所以我仍然可以在Piece中拋出EmptyStringException,但是不必每次都嘗試/抓住我需要創建一個新的棋子?

回答

7

使用運行時異常:

public class EmptyStringException extends RuntimeException 

而不是純Exception。您仍然可以在方法聲明中使用文檔您的異常,但您不強制客戶端代碼處理異常。

+2

可以並且應該記錄。 '如果JavaDoc中的{@code name}爲空,則@throws EmptyStringException。 – pickypg 2011-04-26 19:38:58

0

所以,即使我根本無法創建EmptyStringException,我仍然必須嘗試/捕獲異常。

你是什麼意思?您的Piece構造函數聲明爲throws EmptyStringException。所以就編譯器而言,它可以拋出一個EmptyStringException,只是因爲你已經這麼說了。

1

品牌EmptyStringException延伸RuntimeException。編譯不會抱怨在throws子句中缺少的方法中引入的任何RuntimeException

請注意,您甚至可以在throws子句中包含該例外以記錄您將其拋出。除文檔之外,這不起作用。

對於調用者應該處理的異常,您應該只使用已檢查的異常(這些異常直接來自java.lang.Exception)。你不應該使用他們的東西,「可能發生」,如:

  • 超出內存
  • 參數錯誤
  • IO異常(在Java RT有錯誤的,現在作爲一個完美的「怎麼不行它「示例)
+0

感謝您詳細闡述何時應該使用檢查的異常,異常的那部分需要一些清爽:)。 – Aerus 2011-04-26 19:56:30

1

由於您無法從父構造函數捕獲異常,我會按照其他提供的建議並使您的異常爲RuntimeException或使用現有異常IllegalArgumentException。

如果您處於無法修改基類或更改拋出的異常並且工廠方法可以正常工作的情況。

public class King { 
    private King() { 
     super("King"); 
    } 

    public King createInstance() { 
     try { 
     new King(); 
     } catch (EmptyStringException e) { 
     throw new RuntimeException("Unexpected expection thrown", e); 
     } 
    } 
} 

但在你的情況下,只是有一塊拋出一個RuntimeException是一個更乾淨的解決方案。

此外,如果Piece的構造函數僅由子類調用,請考慮使其受保護並使用assert語句來檢測空名稱。

編輯 - 刪除了不正確的意見

+2

我試着修改King的構造函數,但實際上給了我一個錯誤,說'超'應該是構造函數中必須完成的第一件事。也許我還是做錯了什麼... 另外,感謝提及使它受到保護。作爲@Aerus提到的 – Aerus 2011-04-26 19:52:24

+0

-1,這在Java中是非法的。 – 2011-04-26 20:01:26

+0

在這種情況下,我只會使用assert或IllegalArguementException。 – 2011-04-26 20:23:15

0

我不願意用RuntimeExceptions因爲這種短路內置執法,所有excetions在什麼地方處理。是的,在你的King對象中,異常不會發生,這是一個內部編碼錯誤,所以RuntimeException可以說是適當的。但是你的Piece對象顯然不是這種情況。

Java的令人討厭的規則,即super()必須是第一個語句,可以防止您在King構造函數中捕獲錯誤。

我在某些程序中使用的替代方法是將所有構造函數代碼移動到普通函數,然後讓構造函數調用此函數。像:

public class Piece 
{ 
    public Piece(String name) throws EmptyStringException 
    { 
    initPiece(name); 
    } 
    // Protect so outsiders must use legal constructors 
    protected Piece() 
    { 
    // nop 
    } 
    protected void initPiece(String name) throws EmptyStringException 
    { 
    if (name.length()==0) 
     throw new EmptyStringException(); 
    pieceName=name; 
    } 
} 
public class King extends Piece 
{ 
    public King(boolean white) 
    { 
    try 
    { 
     initPiece("King"); 
    } 
    catch (EmptyStringException panic) 
    { 
     throw new RuntimeException(panic.toString()); // should never happen 
    } 
    } 
} 

換句話說,避免需要調用super。調用別的東西來完成初始化。那麼超級特殊規則就不適用了。

另一種選擇是爲King創建工廠方法,而不是構造函數。說:

public class Piece 
{ 
    public Piece(String name) throws EmptyStringException 
    { 
    if (name.length()==0) 
     throw new EmptyStringException(); 
    pieceName=name; 
    } 
    public Piece makeKing(boolean white) 
    { 
    try 
    { 
     return new Piece("King"); 
    } 
    catch (EmptyStringException e) 
    { 
     throw new RuntimeException(e.toString()); // won't ever happen 
    } 
    } 
} 

如果國王真的需要成爲自己的班級,你仍然可以做到這一點,這是相同的概念。