【问题标题】:Does it make sense to re-throwing exception in catch block?在 catch 块中重新抛出异常是否有意义?
【发布时间】:2012-12-11 14:48:24
【问题描述】:

从 catch 块中抛出异常只是为了记录消息以便我们确定导致异常的原因是否有意义?

代码

  public void saveLogs(Logs logs) throws RemoteException
  {
        try
        {
            LogsOps.saveLogs(logs);
        }
        catch (RemoteException e)
        {
            log.info("RemoteException is thrown while trying to save logs ", e);
            throw new RemoteException("RemoteException caused while trying to save", e);
        }
    }

为了响应下面的其中一个 cmets,此方法会抛出 StackOverFlow 异常,这里是 log.info 的实际实现,它只显示这些错误。

     /** Log the message and the exception with a level of INFO.
     * @param message - The message text.
     * @param t - An exception to display.
     */
    public void info(Object message, Throwable t)
    {
        String nullSafeMessage = (message != null) ? message.toString() : t.getClass().getSimpleName();
        log.info(nullSafeMessage, t);
    }

所以永远不会抛出 Stackoverflow 异常。

【问题讨论】:

  • 堆栈跟踪是否包含来源,并且消息应尽可能具有描述性以避免这种情况。但我已经看到它完成了,很少。除非没有其他东西会记录它。
  • 您实际上是在记录异常引发的记录?那将是 StackOverFlow 异常!
  • @TejaswiRana:我没有看到它抛出 StackOverFlow 异常,你为什么认为它会抛出 Stack Over Flow 异常?,请参阅我更新的问题。
  • 如果 LogOps.saveLogs(logs) 实际上抛出 RemoteException 它不会被捕获。不过只是好奇-> SaveLogs 中的日志和log.info 中的日志是两个不同的东西?在我看来它们是同一件事,log.info 实际上并没有写入,而是保存到日志集合中,然后以一定的时间间隔保存。
  • log.info 是我们正在使用的标准记录器,而保存日志是应用程序中的页面,它捕获有关每个解析作业请求的解析日志的详细信息,希望这可以澄清。

标签: java exception


【解决方案1】:

这取决于更高层捕获异常的方法。如果没有任何 else 会记录该消息,那么当然,这是有道理的 - 尽管我可能会重新抛出 original 异常而不是创建一个新异常:

catch (RemoteException e)
{
    log.info("RemoteException is thrown while trying to save logs ", e);
    throw e;
}

不过,理想情况下,您应该在堆栈更高的位置有一个 catch 块,这样可以适当地记录 - 如果您只是记录异常,那么无论如何都可以获得所有信息.

当您想要记录异常中存在的信息(例如参数值)时,捕获/记录/重新抛出是有意义的。

【讨论】:

  • 同意,但在我的情况下,我正在使用通用日志消息捕获更高级别的异常,但我想捕获有关为什么以及何时抛出当前 RemoteException 的特定消息,以便调试应用程序更容易当我们遇到一些问题时的观点。
  • @Rachel 我知道的任何该死的记录器都会打印方法名称和类名称,因此您不需要特定信息。如果您只想打印消息并继续前进,也可以使用Exception.getMesssage
【解决方案2】:

假设您最终会处理传播的异常,这种 catch-log-rethrow 策略只会弄乱日志文件。想象一下,这是在堆栈跟踪的整个过程中完成的——你最终会得到大量没有用处的冗余错误信息。

如果你没有处理异常,你也不应该记录它。

【讨论】:

    【解决方案3】:

    除了日志记录之外,这种方法还可用于在失败的情况下执行必要的清理,然后再将控制权返回给堆栈中的调用者。

    例如

    InputStream is = new InputStream( ... )
    
    try {
    
        is.read(...);
    
        return is;
    
    } catch ( IOException ioe ) {
        is.close();
        throw ioe;
    }
    

    当然,这是一种有些特殊的用法,大多数情况下可以通过使用 finally 子句优雅地避免 - 但并非总是如此,如上例所示。

    【讨论】:

      猜你喜欢
      • 2014-06-19
      • 1970-01-01
      • 1970-01-01
      • 2016-12-11
      • 1970-01-01
      • 2011-03-25
      • 2011-03-18
      • 1970-01-01
      相关资源
      最近更新 更多