[英]Java: How to propagate a "method exit" when tucking-in exceptions?
return
或throw new...
編譯器認為方法結束-如果您能告訴我“方法退出”的可接受詞,我將進行編輯問題我的問題如下:
我做了很多throw new RuntimeException(...
所以,我決定把它“ public static void quickRaise (String msg) { throw new RuntimeException(msg); }
去”: public static void quickRaise (String msg) { throw new RuntimeException(msg); }
public static void quickRaise (String msg) { throw new RuntimeException(msg); }
然后我可以重復使用它。
(這將幫助我在未來增強有關引發運行時異常的過程,甚至切換到自定義 Exception 類,而無需在代碼中尋找異常拋出)
但是,在我可以寫之前的地方:
public MyType doSomething() { try { //... return new MyType (parameter); } catch (Exception e) { throw new RuntimeException("msg") } }
並且編譯器會正確理解“此方法要么通過返回退出要么通過拋出退出”,因此沒有邏輯上的“死胡同”
當我將throw new RuntimeException("msg")
更改為quickRaise("msg")
,編譯器不再認為我的方法“完成”。 它抱怨缺少 return 語句,即使quickRaise
在語義上等同於throw
(或者至少這是我想要做的!)
讓我嘗試通過一個重現的例子來重申這個問題(這將無法編譯,這就是問題所在):
public static void main(String[] args) {
System.out.println(doSomething());
}
public static String doSomething () {
try {
//... Some fun stuff going on here
return "Something";
} catch (Exception e) {
quickRaise("Could not find handshakes");
//throw new RuntimeException("If you uncomment this line, it will compile!");
}
}
public static void quickRaise (String msg) {
throw new RuntimeException(msg);
}
你的想法是非常不可取的。
例如,這只是糟糕的代碼風格:
try {
someIO();
} catch (IOException e) {
throw new RuntimeException("Problem with IO");
}
糟糕的原因是您現在已經抹去了有關問題的實際信息。 該信息被鎖定在您剛剛捕獲的異常的 5 個獨立部分中:它的類型(例如FileNotFoundException
、它的消息(例如“目錄 /foo/bar 不存在”)、它的堆棧跟蹤、它的因果鏈和作為 throwables是對象,該特定類型異常的任何特定額外細節(例如某些 SQLException 的特定於 DB 引擎的錯誤編碼)。
扔掉這些信息是愚蠢的。
要解決此問題,您只需添加原因:
} catch (IOException e) {
throw new RuntimeException("IO problem", e);
}
現在 IOException 被標記為您拋出的異常的原因,這意味着在錯誤日志中您將看到它 + 消息 + 它的堆棧跟蹤 + 任何原因的堆棧跟蹤。
要讓編譯器意識到該方法到此結束,您需要做的就是拋出它:
public static RuntimeException quickRaise(String msg) {
throw new RuntimeException(msg);
return null; // doesn't matter, we never get here
}
// to use:
throw quickRaise(msg);
但是,正如我之前所解釋的,這是一個非常糟糕的主意。
其次,“我只是想拋出一個異常,也許以后我想替換我拋出的那種異常”的想法也沒有真正解決:你需要為這種情況選擇一個合適的異常,因此你不能首先編寫一個通用的 throw 方法。
首先,學會接受throws
子句。 如果您的方法從根本上執行 I/O(例如,它的 javadoc 和/或名稱使其顯而易見,例如saveGame(Path p)
或scanUserHome
),則應聲明它throws IOException
。
如果您的方法是一個入口點(例如,它是您自己的代碼開始運行的第一個點),那么您的方法應該聲明為throws Exception
。 例如,您的public static void main()
方法應該throws Exception
。 有時入口點不是主要的而是其他東西(例如 webhandler 路由鈎子),有時向后愚蠢的 franeworks 阻止你這樣做,但往往有一個包裝功能(例如} catch (Exception e) { throw new ServletException(e); }
)。
對於既 [A] 基本上不是方法目的的一部分,而是實現細節的更多部分的異常,[B] 不太可能出錯,除了硬崩潰之外,你無能為力,然后,是的,重新包裝為 RuntimeException。 對於所有此類異常,在“全局”更改此值並沒有多大意義。 充其量你遲到地意識到失敗的可能性比你最初想象的要大一點,要么為其創建一個適當的例外並記錄這種行為。 但這又是基於每個方法,而不是您可以以一攬子方式應用的東西。
您的方法從根本上與編譯器需要查看流程在 throw 語句處終止的需求不一致。
我建議使用一個只構造一個異常的實用方法,然后您從原始點拋出該異常。
在每次調用 quickRaise() 之后,它不是或放置虛擬返回。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.