第75项:在详细信息中包含捕获的失败信息

  当程序由于未被捕获的异常而失败的时候,系统会自动地打印出该异常的栈跟踪信息。在栈跟踪信息中包含该异常的字符串表示法(string represention),即它的toString方法的调用结果。它通常包含该异常的类名,紧随其后的是详细信息(detail message)。通常,这只是程序猿或者站点可靠性工程师【运维工程师?】(field service personnel,检查软件失败的人)在调查软件失败原因时必须检查的信息。如果失败的情形不容易重现,要想获得更多的信息会非常困难,甚至是不可能的。因此,异常类型的toString方法应该尽可能多地返回有关失败原因的信息,这一点特别重要。换句话说,异常的详细信息应该捕获住失败(capture the failure),以便于以后分析。

  为了捕获失败,异常的详细信息应该包含所有“对该异常有贡献”【触发该异常】的参数和域的值 。例如,IndexOutOfBoundsException异常的详细信息应该包含下界、上界以及没有落在界内的下标值。该详细信息提供了许多关于失败的信息。这三个值中任何一个或者全部都有可能是错误的。实际的下标值可能小于下界或者等于上界(“越界错误”),或者它可能是个无效值,太小或太大。下界也有可能大于上界(严重违反内部约束条件的一种情况)。每一种情形都代表了不同的问题,如果程序猿知道应该去查找哪种错误,它【异常的详细信息】对诊断【错误】的帮助是很大的。

  一个警告涉及安全的敏感信息。由于许多人在诊断和修复软件问题的过程中可能会看到栈跟踪信息,因此请不要在详细信息中包含密码,加密密钥等

  虽然将所有相关数据包含在异常的详细信息中至关重要,但是包含大量的描述信息往往没有什么意义。栈跟踪信息的目的是跟文档结合起来进行分析,如果有需要的话也可以跟源文件结合起来进行分析。它通常包含抛出该异常的确切文件和行数,以及堆栈中所有其他方法调用所在的文件和行数。关于失败的冗长描述信息通常是不必要的,这些信息可以通过阅读源代码而获得。

  异常的详细信息不应该与用户级别的错误信息混为一谈,后者对于最终用户而言必须是可以理解的。与用户层次的错误消息不同,异常的详细信息主要是为了让程序员或站点可靠性工程师在分析故障的时候从中获益。因此,信息内容远比可读性重要。 用户级错误消息通常是本地化的(localized),而异常详细消息很少这么做。

  为了确保在异常的详细信息中包含足够的能够捕获失败的信息,一种办法是在异常的构造器而不是字符串详细信息中引入这些信息。然后可以自动生成包含该信息的【异常】详细信息。例如,IndexOutOfBoundsException可以有一个如下所示的构造函数,而不是String构造器:

/**
* Constructs an IndexOutOfBoundsException.
*
* @param lowerBound the lowest legal index value
* @param upperBound the highest legal index value plus one
* @param index the actual index value
*/
public IndexOutOfBoundsException(int lowerBound, int upperBound, int index) {
    // Generate a detail message that captures the failure
    super(String.format("Lower bound: %d, Upper bound: %d, Index: %d", lowerBound, upperBound, index));
    // Save failure information for programmatic access
    this.lowerBound = lowerBound;
    this.upperBound = upperBound;
    this.index = index;
}

  从Java 9开始,IndexOutOfBoundsException最终获得了一个带有int值索引参数的构造函数,但遗憾的是它省略了lowerBound和upperBound参数。更一般地说,Java类库并没有大量使用这个习惯用法,但强烈建议使用它。它使程序员很容易【通过】抛出【的】异常来捕获失败。事实上,这种做法使程序猿不想捕获失败都难!实际上,这种做法可以有效地把代码几种起来放在异常类中,由这些代码对异常类自身中的异常产生高质量的详细信息,而不是要求类的每个用户都多余地产生详细信息。

  正如第70项中所建议的,为异常的捕获失败(failure-capture)的信息提供一些访问方法是合适的(在上述例子中的lowerBound、upperBound和index方法)。相对于未受检异常,为受检异常提供这样的访问方法更为重要,因为捕获失败的信息对于【将程序】从失败中恢复【正常】是非常有用的。程序猿希望通过程序的手段来访问未受检异常的细节,这很少见(尽管也是可以想象得到的)。然而,即使对于未受检的异常,作为一般原则提供这些访问方法也是明智的(第12项,原书57页)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值