5

我有一段代码在 JSON 字符串中编码某种业务数据:

public String encodeDataAsJsonString(Data data) throws JSONException {
    JSONObject o = new JSONObject();
    o.put("SomeField1", data.getSomeProperty1());
    o.put("SomeField2", data.getSomeProperty2());
    ...
    return o;
}

事情是:

  • JSONException 是一个检查异常,但是
  • 我真的不知道如何在编译时处理它。如果 JSONException 真的发生,它可能是代码中的一个错误,应该由已经存在的常规“全局未捕获异常处理程序” (例如this)处理,并且已经执行了所有必要的日志记录和清理。

因此,我最终在调用方法中这样做了:

...
try {
    encoded = encodeDataAsJsonString(data);
} catch (JSONException e) {
    throw new RuntimeException(e);
}
...

这似乎比在调用堆栈上的每个方法中throws JSONException添加a更小。但是,它仍然感觉很脏,因此我的问题是:

如果我想要一些特定的已检查异常走“常规未检查异常路线”,是否将其重新作为 RuntimeException 使用正确的习惯用法?

4

6 回答 6

6

情况很简单:如果你的异常没有商业价值,也就是说,它只是一个失败,一定要使用未经检查的异常。如果您需要以特定于该异常的方式处理该异常,这在大多数情况下意味着处理代码会涉及业务逻辑,那么使用未经检查的异常仍然可以,但是使用未检查的异常至少有一些好处检查异常。但是,无论哪种情况,您从 JSON API 获得的原始异常都是无用的,它只是公共 API 设计不佳的标志。

作为旁注,有一个“偷偷摸摸的抛出”习语,它允许您在不包装的情况下抛出原始的检查异常:

public static <R> R sneakyThrow(Throwable t) {
  return UncheckedThrower.<RuntimeException, R>sneakyThrow0(t);
}
@SuppressWarnings("unchecked")
private static <E extends Exception, R> R sneakyThrow0(Throwable t) throws E { throw (E)t; }

不用说,在项目中使用这种方法时应该非常小心。

于 2012-10-22T17:45:19.443 回答
5

简短的回答,是的。

您可能可以创建自己的异常类(运行时异常的子类)并重新抛出它以使其更容易记录,在必要时捕获/处理它。像休眠这样的事情通过使用 HibernateException 来实现,客户端/调用代码不会强制捕获它,但当可以使用它完成某些逻辑/应用程序特定的事情时,它总是可以捕获它。

于 2012-10-22T17:32:06.347 回答
2

好吧,如果您不打算在应用程序代码中处理异常,那么您可以将其作为RuntimeException.

我更喜欢用它com.google.common.base.Throwables来传播这个。

于 2012-10-22T17:57:11.337 回答
1

在 Java 代码中使用未经检查的异常是有争议的。如果您想遵循这种方法,那么像您所做的那样包装已检查的异常是唯一明智的做法。FWIW,我已经多次使用这种方法并且它很有用。

即使您不想接受这种风格,将一些已检查的异常转换为运行时异常可能仍然有用。

于 2012-10-22T17:33:39.980 回答
1

我一直这样做。是的,这是一个很好的方法。不,这不是一种肮脏的方法。就个人而言,我不能忍受检查异常。我将所有检查的异常包装为运行时异常,无论它是什么类型的异常。

于 2012-10-22T17:33:46.377 回答
0

检查异常是开发人员之间进行交流的一种方式。检查的异常说“处理我”。如果您知道自己在做什么,则可以重新抛出异常(并记录)。

编辑:与其他答案一样,重新包装异常也是很好的建议。

于 2012-10-22T17:33:21.507 回答