简体   繁体   English

使检查异常成为RuntimeException

[英]Making a checked exception a RuntimeException

I'm working on a legacy system that has a custom exception that's used gosh-frickity-everywhere. 我正在使用一个具有自定义异常的遗留系统,该异常使用了gosh-frickity-everywhere。 It was inspired by the ServletException class, that said "well any time you have an exception in your Servlet, you'll want to throw this ServletException ". 它受到ServletException类的启发,它表示“好吧,只要Servlet中有异常,就要抛出该ServletException ”。

As the system evolved (over 10 years) a more robust system of catching the exceptions at a higher level has taken place and it's no longer necessary to wrap every exception in this custom exception. 随着系统的发展(超过10年),已经出现了一个更强大的系统来捕获更高级别的异常,不再需要将所有异常包装在此自定义异常中。 (One could argue it never was, but that's another story. It's a stable app, so I tend not to complain too much!!) But we're not going to be refactoring them all at once, just slowly over time. (可以说从来没有,但是那是另一回事了。它是一个稳定的应用程序,所以我不会抱怨太多!!)但是我们不会立即重构它们,只是随着时间的推移会慢慢地重构它们。

However, one thing that would make things simpler going forward would be if the custom exception were a runtime exception instead of a checked exception. 但是,使自定义异常是运行时异常而不是检查异常是使事情变得更简单的一件事。 This way we wouldn't need to explicitly catch it everywhere, and legacy code that hasn't been refactored yet will just continue to throw this the same way as they'd throw a null pointer exception if one occurred. 这样,我们就不需要在任何地方显式捕获它,而尚未重构的旧代码将继续以与抛出空指针异常(如果发生的话)相同的方式抛出此异常。

My question is... What are the side effects of taking a once checked exception and making it a runtime exception? 我的问题是... 接受一次检查的异常并使其成为运行时异常有什么副作用?

I can't think of any, aside from warnings for unnecessary check and throws declarations, but it would be nice to get input from someone who has been down this road before. 除了不必要的警告和引发声明的警告外,我想不出任何办法,但是最好还是从以前走过这条路的人那里得到意见。

Changing a checked exception into an unchecked one has very little practical effect on existing, working code, but you do need to watch out for the possibility that somewhere in your code you catch (RuntimeException ...) . 将一个已检查的异常更改为一个未检查的异常对现有的工作代码几乎没有实际影响,但是您确实需要注意在代码中某个地方被catch (RuntimeException ...)的可能性catch (RuntimeException ...) Such catches do not intercept your custom exception now, but they would do if you make it unchecked. 这样的捕获现在不会拦截您的自定义异常,但是如果您不对其进行检查,它们就会这样做。

You might also run into issues if you do anything reflective related to methods that throw that exception (which apparently is most of them). 如果您做任何与引发该异常的方法相关的事情(这显然是其中的大多数),也可能会遇到问题。

Something like that happened on an old module of a app that I had to maintain. 类似的事情发生在我必须维护的应用程序的旧模块上。 The only problem translating exceptions to runtime is that you may lose granularity but that is entirely up to you to handle. 将异常转换为运行时的唯一问题是您可能会失去粒度,但这完全取决于您的处理。

For example, we had a ton of code like this in the deeper layers: 例如,在更深的层中,我们有大量这样的代码:

catch(IOException e){    
    Throwables.propagate(e);
}

We used that pattern carelessly all over that layer and, when we needed to check the exception cause, we always had to get the cause of the exception and that made a lot of boilerplate in higher layers. 我们在整个层上都粗心地使用了该模式,并且当我们需要检查异常原因时,我们总是必须找出异常原因,这在高层中产生了很多样板。 To this day I believe it's better to create a good class hierarchy of non-checked exceptions in order to preserve granularity. 到目前为止,我相信最好创建一个良好的非检查异常类层次结构,以保持粒度。 eg 例如

catch(IOException e){
    throw new FileNotCreatedException(e);
}

And with this you can catch the exception easily in other layers and divide errors and fallbacks easily: 这样,您可以轻松地在其他层中捕获异常,并轻松划分错误和后备:

catch(FileNotCreatedException e){
   notifyError(e);
} catch(NoMoreStorageException e){
   releaseSomeStorage();
   retryOperation();
}

Here are a few that I can think of 我可以想到的一些

  • Runtime exceptions could potentially go to a layer where you didnot intend it to go. 运行时异常可能会到达您不希望执行的层。
    • ex: a Servlet ---> Service ---> DAO. 例如:一个Servlet --->服务---> DAO。 Runtime exceptions thrown by DAO related to database interactions could potentially land up on Servlet. DAO引发的与数据库交互相关的运行时异常可能会落在Servlet上。 Clear segregation of layers where each layer handles all exceptions (checked/runtime) at its entry points can ensure that this doesn't happen. 清晰地隔离各个层,其中每个层在其入口点都处理所有异常(已检查/运行时),可以确保不会发生这种情况。
  • Runtime exceptions can leave system in an inconsistent state. 运行时异常可能会使系统处于不一致状态。
    • ex: If the sequence diagram looks like Class A --> Class B ---> Class C and if Class B1 is injected between B and C therefore Class A ---> Class B ---> Class B1 ---> Class C then neither Class A, B, B1 would know that they might have to cleanup when this runtime exception occurs in Class C. In fact this can potentially affect the semantics of any dependency injection. 例如:如果序列图看起来像A级-> B级---> C级,并且如果B1级被注入到B和C之间,那么A级---> B级-> B1级->然后,类C,类A,B,B1都不知道在类C中发生此运行时异常时可能必须清除它们。实际上,这可能会影响任何依赖项注入的语义。

As a general thumb rule in my opinion: 我认为一般的经验法则是:

  • Use checked exceptions when you "expect" the exception as part of a normal control flow and know how to handle it. 当您“期望”异常作为常规控制流的一部分并知道如何处理时,请使用检查的异常。 ex: Validation of a business rule say account balance has to be greater than debit amount by atleast 100. 例如:验证业务规则后,帐户余额必须至少大于借方金额100。
  • Use unchecked exceptions when you "don't expect" the exception as part of a normal control flow hence have no means of handling it yet you know that "some class" within your "layer" would handle it to ensure graceful degradation ex: DB connection lost would have handled by your "service" layer entry class. 当您“不希望”将异常作为正常控制流的一部分使用时,请使用未经检查的异常,因此无法对其进行处理,但您知道“层”中的“某些类”将对其进行处理以确保正常降级,例如:DB连接丢失将由“服务”层条目类处理。
  • Never use error. 永远不要使用错误。 Only JRE has reasons to throw errors. 仅JRE有引发错误的原因。

暂无
暂无

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

相关问题 不会引发检查的异常并将其转换为RuntimeException - Checked exception is not thrown and turned into RuntimeException 引发检查异常与引发包装的RuntimeException - Throwing Checked Exception vs Throwing a wrapped RuntimeException 为什么在Java中未选中Exception类,因为未选中其子类RuntimeException? - Why Exception class is checked as its child class RuntimeException is unchecked in Java? Spring Webflux - 抛出已检查的自定义异常(不是 RuntimeException)的正确方法 - Spring Webflux - Proper way to throw checked custom exception (not RuntimeException) 为什么Class CloneNotSupportedException是一个已检查的异常,而不是扩展RuntimeException? - Why Class CloneNotSupportedException is a checked Exception and does not extend RuntimeException instead? 将检查的异常作为RuntimeException抛出可能会导致什么问题? - What issues may ensue by throwing a checked exception as a RuntimeException? 是什么让子类(即 RuntimeException 未检查)和 Exception 被检查成为可能? - What make it possible that child class i.e. RuntimeException is unchecked and Exception is checked? 所有RuntimeException / Unchecked异常倡导者,您将如何处理这种情况? - All RuntimeException / Un-checked exception advocates, how would you handle this scenario? 将RuntimeException转换为Checked是一种好习惯吗? - Is it good practice to convert RuntimeException to Checked? 在java中扩展Exception / RunTimeException? - Extending Exception/RunTimeException in java?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM