首页 > 解决方案 > 为什么 Throwable.getCause 在返回 `null` 之前检查“原因”是否为“this”,而不是直接返回原因?

问题描述

我今天有理由进入源代码,Throwable.getCause在这种方法中看到这段代码有点惊讶:

    public synchronized Throwable getCause() {
        return (cause==this ? null : cause);
    }

这是来自 Java 1.8,但在我查看的更高版本中看起来相同。

我的问题是:为什么不简单return cause地完成它呢?

标签: javaexception

解决方案


编码:

 public synchronized Throwable getCause() {
     return (cause==this ? null : cause);
 }

说如果causethis返回,null否则返回cause(这也可能是null发生的。

故事从这个开始:private Throwable cause = this;我相信所有版本> = 1.4都是一样的。这将原因初始化为这个对象!

目的是Throwable对象是不可变的,但它提供了一种方法,该方法void initCause(Throwable cause)只能调用一次来初始化原因或由构造函数初始化的原因。

正如文档所解释的那样,允许将原因链接到之前添加的子类,这些子类cause不包含在它们的构造函数之一中。

所以这个类想知道是否initCause已经被调用并抛出IllegalStateException它(我的评论):

public Throwable initCause(Throwable cause) {
    if (cause == this) //Illogical! An exception can't be self caused!
            throw new IllegalArgumentException();
    if (this.cause != this)// false if cause has been initialised 'properly'.
        throw new IllegalStateException();
    this.cause = cause;
     return this;
}

该类cause==this用于指示cause未设置。它不能使用cause==null,因为它null是一个有效值。所以它使用了cause==this因为主动设置cause为的异常状态this是自致异常的不合逻辑状态。

它确实有效。但这真的是个好主意吗?我说不是。它将“原因未设置”和“原因已设置并设置为null”的状态混为一谈。一个不那么扭曲的设计只是引入一个标志private boolean isCauseSet=false;并设置它如果initCause曾经被调用或设置它的构造函数被调用。

我们在其中看到的复杂代码Throwable只不过是避免了boolean. 在里面保存一个boolean字段Throwable似乎并不值得费心。任何有用的应用程序都不会有这么多Throwable的对象在流通中。


推荐阅读