簡體   English   中英

在沒有拋出聲明的情況下從泛型方法傳播異常

[英]Propagating an exception from a generic method without throws declaration

我有一個簡單的界面

public interface Func<I, O> {
    public O apply(I i);
}

我有一個類,有一堆私有(靜態)類實現該接口,就像這樣

import org.json.*;
public static class Baz {
    public static B Qux(String jsonSource) throws JSONException {
        JSONObject m = new JSONObject(jsonSource);
        return new Baz.Foo().apply(m);
    }

    private static class Foo implements Func<JSONObject, B> {
        public B apply(JSONObject f) {
            JSONObject x = f.getJSONObject("bar");
            /* Whatever other code in here */
            return new B(); /* Place-holder */
        }
    }
}

由於JSONObjects上的任何操作都需要捕獲JSONException ,因此編譯器會在JSONObject x = f.getJSONObject("bar");抱怨未被捕獲和未聲明的異常JSONObject x = f.getJSONObject("bar"); 認為我可以簡單地將該特定應用於try-catch並重新拋出調用者的異常,我嘗試了它,如下所示:

private static class Foo implements Func<JSONObject, B> {
    public B apply(JSONObject f) {
        try {
            JSONObject x = f.getJSONObject("bar");
            /* Whatever other code in here */
            return new B(); /* Place-holder */
        catch (JSONException e) {
            throw e;
        }
    }
}

但是,我現在得到error: unreported exception JSONException; must be caught or declared to be thrown error: unreported exception JSONException; must be caught or declared to be thrown指向throw e;

我不明白為什么這不起作用。 正如預期的那樣,進一步包裝apply調用沒有任何新功能。

我的問題是:

  1. 為什么這不起作用?
  2. 我該如何解決?

我相信解決方法是讓我的接口接受異常類型。 我不確定這種語法是否有效,但我想我可以做一些事情

public interface FuncEx<I, O, E> {
    public O apply(I i) throws E;
}

有更好的方式嗎? 我不認為我必須創建一個全新的界面才能解決這個問題。

已檢查的異常(即不是RuntimeException的子級的異常 - 如JSONException)構成方法簽名的一部分。 如果您調用拋出已檢查異常的方法,則必須處理它,或聲明您自己拋出它。 如果你自己拋出一個檢查過的異常(就像你使用catch / rethrow代碼那樣),你仍然必須聲明它。

如果您不想聲明拋出它,則可以將其包裝在RuntimeException中。 例如:

private static class Foo implements Func<JSONObject, B> {
  public B apply(JSONObject f) {
    try {
        JSONObject x = f.getJSONObject("bar");
        /* Whatever other code in here */
        return new B(); /* Place-holder */
    catch (JSONException e) {
        throw new RuntimeException("Could not get bar", e);
    }
  }
}

關於何時拋出已檢查的異常而不是RuntimeExceptions的想法有很多種。 對我來說,我的第一個指導原則是,如果你能夠合理地期望調用者以有意義的方式響應異常(而不僅僅是重新拋出它),那么將它作為一個經過檢查的異常。 否則使它成為RuntimeException。

這是一篇關於這個主題的優秀文章: http//onjava.com/pub/a/onjava/2003/11/19/exceptions.html

暫無
暫無

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

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