简体   繁体   English

将检查的异常作为RuntimeException抛出可能会导致什么问题?

[英]What issues may ensue by throwing a checked exception as a RuntimeException?

I have a piece of code that encodes some kind of business data in a JSON string: 我有一段代码在JSON字符串中编码某种业务数据:

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

The thing is: 事情是:

  • JSONException is a checked exception, but JSONException是一个已检查的异常,但是
  • I don't really know how to handle it at compile time. 我真的不知道如何在编译时处理它。 If a JSONException really occurs, it's probably a bug in the the code and should be handled by the regular "global uncaught exception handler" which is already there (eg this ), and which already performs all the necessary logging and cleaning up. 如果真的发生了JSONException,它可能是代码中的一个错误,应该由已经存在的常规“全局未捕获异常处理程序”(例如这个 )处理,并且已经执行了所有必要的日志记录和清理。

Thus, I ended up doing this in the calling method: 因此,我最终在调用方法中执行此操作:

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

It seemed like a lesser evil than adding a throws JSONException to every method up the call stack. throws JSONException向调用堆栈中的每个方法添加throws JSONException似乎是一个小恶魔。 However, it still feels dirty, hence my question: 但是,它仍然感觉很脏,因此我的问题是:

If I want some specific checked exception to go the "regular unchecked exception route", is rethrowing it as a RuntimeException the correct idiom to use? 如果我想要一些特定的检查异常去“常规未经检查的异常路由”,是否将它重新抛出为RuntimeException正确使用的习惯用法?

The situation is quite simple: if your exception has no business value, that is, it is just a failure, definitely use an unchecked exception. 情况非常简单:如果您的异常没有业务价值,也就是说,它只是一个失败,肯定会使用未经检查的异常。 If you need to handle the exception in a way specific to that exception, which in most cases means that the handling code will involve business logic, then it is still OK to use an unchecked exception, but there are at least some benefits in using a checked exception. 如果您需要以特定于该异常的方式处理异常,这在大多数情况下意味着处理代码将涉及业务逻辑,那么使用未经检查的异常仍然可以,但使用a时至少有一些好处检查异常。 However, in either case the raw exception you get from the JSON API is useless and it is only a sign of bad public API design. 但是,在任何一种情况下,从JSON API获得的原始异常都是无用的,它只是公共API设计不良的标志。

As a side note, there's the "sneaky throw" idiom which will allow you to throw your original checked exception without wrapping: 作为旁注,有“偷偷摸摸”的习惯用法,它可以让你在没有包装的情况下抛出原始的检查异常:

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; }

Needless to say, you should be very careful about using this approach in a project. 不用说,在项目中使用这种方法时应该非常小心。

Short answer, yes. 简短的回答,是的。

You could probably create your own exception class (a child of runtime exception) and re throw that to make it easier to document, catch/ handle it where necessary. 您可以创建自己的异常类(运行时异常的子代)并重新抛出它以便更容易记录,在必要时捕获/处理它。 Something like hibernate does by using HibernateException, client/ calling code is not forced to catch it but can always catch it when something logical/ application specific can be done with it. 像hibernate这样的东西通过使用HibernateException来实现,客户端/调用代码不会被强制捕获它,但是当可以使用它完成逻辑/特定于应用程序的特定内容时,它总能捕获它。

There is an argument for using only unchecked exception in your Java code. 有一个参数只能在Java代码中使用未经检查的异常。 If you want to follow that approach, wrapping checked exception them as you have done is the only sensible thing to do. 如果你想遵循这种方法,那么将你检查过的异常包装起来是唯一明智的做法。 FWIW, I have used this approach many times and it has been useful. FWIW,我多次使用过这种方法,并且它很有用。

Even if you don't want to buy in to that style it may be still be useful to convert some checked exceptions to runtime exceptions. 即使您不想购买该样式,将一些已检查的异常转换为运行时异常仍然很有用。

I do this all the time. 我一直这样做。 Yes it is a good approach to do it. 是的,这是一个很好的方法。 No, it is not a dirty approach. 不,这不是一个肮脏的方法。 Personally, I cant stand checked exceptions. 就个人而言,我无法检查例外情况。 I wrap all checked exceptions as runtime exceptions regardless of what type of exception it is. 我将所有已检查的异常包装为运行时异常,而不管它是什么类型的异常。

Well, if you don't intend to handled the exception in you application code then you can throw it as RuntimeException . 好吧,如果您不打算在应用程序代码中处理异常,那么可以将其作为RuntimeException抛出。

I prefer to use com.google.common.base.Throwables to propagate this. 我更喜欢使用com.google.common.base.Throwables传播此内容。

Checked exception is a way to communicate between developers. 检查异常是开发人员之间进行通信的一种方式。 Checked exceptions says "handle me". 检查过的例外说“处理我”。 If you know what you do, you can rethrow exceptions (and log). 如果你知道你做了什么,你可以重新抛出异常(和日志)。

EDIT: as in other answer rewrap exception is also good advice. 编辑:如在其他答案重写异常也是很好的建议。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM