簡體   English   中英

Java - 覆蓋對象的 toString() 方法,但我必須拋出異常

[英]Java - overriding Object's toString() method, but I have to throw exceptions

我遇到了一個問題,我必須覆蓋 Object 的 toString() 方法,但原始方法不會引發任何異常。 但是,我正在使用一些需要拋出異常的通用代碼。

public String toString() throws EmptyListException, InvalidPositionException
{
    Position<Entry<E>> current = fList.first();
    StringBuilder str = new StringBuilder();
    for(int i = 0; i < size(); i++)
    {
        try
        {
            str.insert(str.length(), current.element().toString() + " ");
            current = fList.next(current);
        }
        catch(Exception e){}
    }
    return str.toString();
}

這是FavoriteList.java 的一部分。 必須拋出這些異常。 如果有任何方法可以以某種方式抑制這些異常或在方法中捕獲它們,那將很有幫助。

最后,我的方法標題必須如下所示:

public String toString()
{ content }

我不在乎方法的結束內容。 只要它編譯我就很好。 我只需要修復標題,但我找不到修復它的方法。 非常感謝您提前。

首先,從toString()拋出異常是一個非常糟糕的主意。 toString()用於很多系統軟件(例如調試器)來生成對象的表示。

第一個優先選擇是做其他事情,可能創建一個可能拋出的不同方法,並在toString()調用該方法,捕獲異常並產生替換輸出,例如

super().toString() + " threw " + exception.toString();

如果你覺得你真的必須扔,你可以這樣做:

    try
    {
        str.insert(str.length(), current.element().toString() + " ");
        current = fList.next(current);
    }
    catch(Exception e){
       throw new IllegalStateExcception(super.toString(), e);
    }

這將受檢異常(派生自 java.lang.Exception)包裝在未經檢查的異常(派生自 java.lang.RuntimeException)中。 無需添加throws子句。

從例外情況來看,我認為這是可能拋出的違規行?:

Position<Entry<E>> current = fList.first();

如果是這種情況,您可以處理該異常。 fList地知道fList是什么,我對 Java 不夠熟悉,無法知道編譯器是否足夠聰明以知道您已經檢查過它,但從邏輯fList ,如果fList可能為空,那么我會檢查它第一的:

if (/* check for an empty or null fList */) {
    return "";
}
// the rest of your code

如果編譯器仍然不喜歡那樣,您可以對另一個 try/catch 采取幾乎相同的方法。 就像是:

try {
    // the rest of your code
} catch (Exception e) {
    return "";
}

那時該方法真的不應該拋出,因為任何異常都會導致簡單地返回一個空字符串。 所以標題應該不需要列出的異常類型。

根據個人喜好,我建議在被捕獲時做一些例外的事情 至少在某處記錄它,即使是調試日志,也不一定是錯誤。 從長遠來看,全面忽略所有可能的例外通常不是最好的想法。

jdk 不會從 toString() 中拋出 CheckedException 是有原因的。 此方法在運行時用於填充對象。 他們不希望在此方法中實現任何此類可能引發異常的代碼或業務邏輯。 無論選中或未選中。

參考單一職責原則, toString() 單一職責是迭代對象的屬性並填充它們。

如果您需要編寫任何業務邏輯,則應將其隔離在其他方法中。 如果您需要從 toString() 拋出異常和特別檢查的異常,那么您需要考慮重構您的代碼。

如果您要覆蓋它,則不能從 toString() 拋出已檢查的異常。 創建一個拋出該異常的方法並從 toString() 調用該方法並捕獲該異常並將其包裝在未經檢查的異常中,

throw new IllegalStateException()throw new RuntimeException()

因此, RuntimeException是有目的的。 運行時異常要么是致命錯誤,無法讓用戶繼續,要么是非常頻繁的操作,例如Arithmetic operation或者說equalshashcode 考慮一種情況,如果hashcode開始拋出一個名為HashCalculationException的異常。 它對HashMap的用戶有什么影響,每次在Map上調用getput都必須捕獲一個異常。 而且,JDK 提供的這些功能的實現都是異常證明的,以保持與其他 JDK 組件的完整性,並且 JDK 期望開發人員保持相同。 這里是你的第一個問題的答案。

現在,你應該拋出一個未經檢查的異常嗎? 這是我的看法。 根據指南,使用toString序列化 Java 對象本身是一個壞主意。 toString應該由記錄器或任何其他單向處理程序使用,您打印的內容與完整性沒有任何區別。 想象一下,您開始使用由toString生成的輸出而不是序列化,並編寫了自己的方法來從中創建一個新對象。 您的對象正在保存大量數據。 並且您進入了一種情況,您的調用者不小心開始在日志中打印對象......想象一下它會執行多少字符串連接,並且性能會受到影響。

所以我在這種情況下的建議是去掉toString如果它用於序列化。 它不是該方法的目的。 為其創建一個單獨的方法。 做同樣的事情相當容易,就像在方法簽名中添加一個新的異常,然后使用它一樣。

您始終可以拋出 Unchecked 異常並稍后捕獲它,但強烈建議不要這樣做。 它失敗的目的。 未經檢查的異常是為了避免,而不是捕捉

更多參考,請在此處閱讀我們關於 RuntimeException 的討論 - https://stackoverflow.com/a/58455577/4675277

捕獲異常EmptyListException,InvalidPositionException,並在控制台中輸出消息。

    public String toString() throws EmptyListException, InvalidPositionException
    {
    Position<Entry<E>> current = fList.first();
    StringBuilder str = new StringBuilder();
    for(int i = 0; i < size(); i++)
    {
    try
    {
        str.insert(str.length(), current.element().toString() + " ");
        current = fList.next(current);
    }

     //here
     catch(EmptyListException, InvalidPositionException e){
       System.out.println(e.getMessage());}
    }
    return str.toString();
   }

EmptyListException異常是由first();引起的。 和InvalidPositionException通過Position>; 因為您是班級客戶,所以必須捕獲異常。

如果你真的需要拋出異常而不用trycatch包圍你的代碼

@override
public String toString(){
     if(...)throw new IllegalStateException("list is empty");
     else if(...)throw new IllegalStateException("position is invalid"); 
     return ...;
}

您可以將try塊放在for循環之外。 為了捕獲fList.first()拋出的異常。

public String toString() throws EmptyListException, InvalidPositionException
{
   try
     {
       Position<Entry<E>> current = fList.first();
       StringBuilder str = new StringBuilder();
       for(int i = 0; i < size(); i++)
       {
            str.insert(str.length(), current.element().toString() + " ");
            current = fList.next(current);
       }
    }
    catch(Exception e){
       e.printStackTrace()
    }
    return str.toString();
}

編輯:記錄異常。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM