我有一个简单的界面
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
没有任何新的内容。
我的问题是:
我相信解决方法是让我的界面接受异常类型。我不确定这种语法是否有效,但我想我可以按照
的方式做一些事情public interface FuncEx<I, O, E> {
public O apply(I i) throws E;
}
有更好的方式吗?我不认为我必须创建一个全新的界面才能解决这个问题。
答案 0 :(得分: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