的java:日志抛出异常

问题描述:

在java中,我想记录异常从一段代码被抛出:的java:日志抛出异常

try 
{ 
    doRiskyThing(); 
} 
catch(Throwable t) 
{ 
    log.warn("too bad"); 
    throw t; 
} 

的问题是,现在我的方法必须声明它抛出的Throwable。另一方面,如果我在finally块中记录异常,我怎么知道抛出了什么异常(并且如果任何异常被抛出)。

您至少可以为未检查的异常和n个catch块编写捕获异常。

try{ 
    .. 
}catch(RuntimeException e){ 
    log(e); 
    throw e; 
}catch(ExceptionException ..){ 
    log(e); 
    throw e; 
} 

这不会改变您的方法的签名。捕捉错误是有点味道。那么,记录和抛出异常也是一种气味。这将重复错误消息。

提前异常处理是从项目硬币JDK 7

这似乎是登录异常的错误地方。在抛出时将它记录在doRiskyThing()中,或者将其记录在应该被捕获的地方。

这应该工作:

try 
{ 
    doRiskyThing(); 
} 
catch(RuntimeException e) 
{ 
    log.warn("too bad"); 
    throw e; 
} 
catch(Exception e) 
{ 
    log.warn("too bad"); 
    throw new RuntimeException(e); 
} 
catch(Error e) 
{ 
    log.warn("too bad"); 
    throw e; 
} 

但它的丑陋,我宁愿有一个catch块,在应用程序的顶层捕捉一切,并将其记录,没有再扔。无论如何,堆栈跟踪可以让您找出问题所在。

您可以记录Throwable,并引发RuntimeException。

在Java中,您必须声明您的方法本身可能抛出的任何异常,因为它被视为方法签名的一部分....也就是说,除了RuntimeException之外,它避免了该规则。如果您愿意,RuntimeException可以将Throwable的消息作为其消息的一部分。然而

try 
{ 
    doRiskyThing(); 
} 
catch(Throwable t) 
{ 
    log.warn("too bad, exception thrown: " + t.getMessage()); 
    throw new RuntimeException("Throwable exception was thrown, message: " + t.getMessage()); 
} 

当心,这可能被认为是不好的做法,并为更长远的代码我们建议你把一个非运行时异常,并在方法的签名定义它。

+0

关于“不好的做法”,实际上,趋势远离检查异常,以支持未检查(“运行时”)异常,您仍然可以在方法签名中定义运行时异常。 – SingleShot 2009-10-04 15:57:30

+0

@SS这是一个非常糟糕的想法的一个原因是,包装在RuntimeException中是更改传播的异常。这使得堆栈中的东西很难处理异常。 – 2009-10-05 01:11:07

删除功能本身捕获的Throwable已经是不好的做法(和许多代码质量检查工具标记为此类)。将它包装在RuntimeException中并重新抛出它?可怕!具有异常层次结构的整个观点受到了破坏。

远离检查异常的'趋势'实际上有点微妙。在架构层之间(或者例如在框架API边界),定义一个或多个有意义的异常类型并在其中包含任何特定于实现的错误(例如查看Spring或Hibernate)是常见做法。

使例外检查与否是风格问题。如果调用者很可能愿意并且能够处理错误情况,那么我会检查它(例如检测到并发更新),否则不检查(例如,数据库连接错误)。未经检查的异常应该通过应用程序代码“冒泡”(即不被捕获)并通过显示某种错误页面/屏幕在高层处理。