2013-03-07 18 views
3

У меня есть простой интерфейсРазмножение исключения из общего метода без бросков декларации

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");. Думая, что я мог бы просто обернуть, что особенно применимы в 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 указывая на throw e;.

Я не понимаю, почему это не работает. Дальнейшая упаковка звонка на apply не принесла ничего нового, как ожидалось.

Мои вопросы:

  1. Почему это не работает?
  2. Как это исправить?

Я считаю, что обходным решением было бы заставить мой интерфейс принять тип исключения. Я не уверен, будет ли этот синтаксис работать, но я думаю, что я могу сделать что-то вдоль линий

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

Есть ли лучший способ ™? Я не думаю, что мне пришлось бы создать совершенно новый интерфейс, чтобы справиться с этим маленьким битком.

ответ

4

Отмеченные исключения (т. Е. Исключения, которые НЕ являются подкласс 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

+0

Отличная статья, спасибо за обмен. – arin