可以处理运行时异常吗?

时间:2013-12-02 12:40:34

标签: java exception-handling

不处理运行时异常通常是一种好习惯。

我有这种情况:

  /**boolean returns false if the method execution fails,
  so that an error can be shown to user*/ 
boolean saveData()
 {
    try
    {
         //Some database calls that throw only Runtime exceptions
     }
     catch(Exception e)
     {
         //Log the exception and return false
         return false;
     }
     return true;

 }

因此,从Servlet调用它将获得一个布尔值。如果它是假的,我们会显示一条消息“Save not sucessful”。这样可以,还是有更好的方法呢?

7 个答案:

答案 0 :(得分:5)

  

可以处理运行时异常吗?

只要你能在那时做一些聪明的事,是的。这种“永远不会捕获运行时异常”纯粹是无稽之谈。您可能也想记录它们并做其他事情。

答案 1 :(得分:5)

  

不处理运行时异常通常是一种好习惯。

这句话暗示了一个错误的前提:问题不是是否,而来捕获运行时异常。

在您的代码中的某个时刻,您肯定应该拥有一个“全能”异常处理程序。这一点称为异常障碍,它在调用堆栈中足够高,可以包含一个完整的工作单元(基本上是一个数据库事务的范围)。 / p>

这应该是你的管理原则:

  • 如果异常必须导致当前工作单元被中止(回滚),那么不会捕获该异常直到异常障碍;

  • 如果异常仅为本地字符,其外观仅表示采用不同的路径处理请求,则执行捕获并及早处理。

请注意,上述内容并未使用无效的检查/未检查区别。大多数现代框架完全避免了检查异常,并且不遗余力地保护程序员免受从低级代码抛出的异常。

在实践中,超过90%的例外都属于第一种中止类型。这就是术语“不可恢复”的含义 - 这意味着您无法继续正在进行的操作,但服务器可以保持运行并处理所有其他请求。我看到很多人把这与“JVM即将死亡”混为一谈,但具有这种意义的例外非常罕见,通常没有特殊的处理代码。

最后,请注意,“catch-all”处理程序不仅应该捕获RuntimeExceptions,还应该捕获Error,因为您希望以相同的方式记录每个异常。如果让异常转义应用程序代码,则不知道它将导致什么行为。请注意,存在一些常见错误,例如StackOverflow和OutOfMemory,它们原则上会导致不可恢复的损坏,因此属于Error层次结构,但在大多数现实案例中 除了中止当前请求之外不会造成任何损害。你肯定不想在第一眼看到这样的错误时关闭你的服务。

答案 2 :(得分:3)

不,捕捉将军Exception会掩盖你不想捕捉的任何其他问题。更好地捕捉特定的例外情况,使意外的人更难以失踪。

答案 3 :(得分:1)

我猜你的问题有两个方面:1)处理RuntimeException作为标题建议和2)处理通用Exception这些是两个不同的事情。

RuntimeExcepton的{​​p> The Javadoc列出了一堆子类(NullPointerException ..等)。如果仔细观察,这些只不过是编程错误,而不是在catch块中处理它们,应该更正代码本身,以便他们这样做不会发生。

处理通用Exception通常被称为不良做法,因为它隐藏了可能需要不同处理的特定例外

但是在类似于你的情况下,如果有一个Servlet给方法调用,那么必须有一种优雅的方式来告诉用户在处理请求时,如果显示堆栈跟踪,应用程序会出现问题。

所以你正在做的事情可能是一种处理方式,作为一种好的做法,记录日志中的错误/异常并纠正任何RuntimeException

答案 4 :(得分:1)

  如果方法执行失败

boolean返回false,     这样就可以向用户显示错误

这是抛出异常的方法的明确原因。这就是为什么异常机制首先存在的原因。最佳做法是对这些类型的情况使用异常,而不是布尔信号。

无论何时你遵循这种模式,你都会受到各种各样的影响

  • 来电者无法确定究竟发生了什么。沟通失败了吗?数据是否已损坏?当你返回一个简单的“失败”信号时,无法判断。
  • 由于来电者无法知道发生了什么,因此您会取消来电者的选项。也许调用者可以在某些错误情况下做某事。
  • 您增加了数据错误的可能性。同样,由于调用者无法知道失败的原因,调用者可以对其失败原因做出假设,并在整个程序停止的情况下继续。如果程序继续,它可能决定在真正停止时处理无效数据。

我强烈建议您阅读 Effective Java 中有关异常处理的部分。基本上,如果你不能在方法中对Exception做任何有意义的事情,你应该允许它向上传递堆栈。 在最糟糕的情况下,您引用的API会抛出一个通用的已检查异常,为您提供三种选择之一(编辑:更改为void返回类型,因为布尔返回类型为no更长的任何意义 - 你成功或抛出异常

创建自己的。

 // "MyFatalException" would be a checked Exception 
 public void saveData() throws MyFatalException{
        try{
           // ... do stuff that throws Exception
        }catch(Exception e){
           throw new MyFatalException("Unable to save Data due to a general exception"+
                                      " thrown by foo.bar()", e);
        }
 }

- 输入现有类型(我的偏好是针对RuntimeException的子类

public void saveData() throws IllegalStateException{
        try{
           // ... do stuff that throws Exception
        }catch(Exception e){
           throw new IllegalStateException("Unable to save Data due to a general exception"+
                                      " thrown by foo.bar()", e);
        }

-Declare抛出一个通用的Exception并让它通过(我不推荐这个,但你会看到许多开发人员这样做)

 public void saveData() throws Exception{
       // no try/catch needed.  Just make the call
 }

答案 5 :(得分:0)

一般概念是框架或API仅在错误在代码中无法恢复的情况下才会抛出RuntimeException。例如:您的Db已关闭,或者您的服务器套接字已关闭等等。 虽然抓住这些例外也不错,但实际上是深思熟虑的是你在抓住它们后打算做什么。例如:人们更喜欢捕获数据库级别的连接问题和错误,这些问题是运行时异常子类并在其网站上显示错误页面。检查异常通常用于代码级别的情境案例,捕获它们和处理是代码应该做的事情。

答案 6 :(得分:0)

如果您尝试这样的事情,因为您不希望您的用户出现错误页面,您可以这样做,只要您在此之前发现了所有其他例外情况。

boolean saveData()
 {
    try
    {
         //Some database calls that throw only Runtime exceptions
     }catch(db_Connectivity_Exception e){
         //exception like credentials invalid
     }catch(db_table_Exception e){
         //table desc. changed
     }
     catch(Exception e)
     {
         //Log the exception and return false
         //Since you are going to log your error I hope is not harmfu
         return false;
     }
     return true;

 }

这仍然不是最佳做法