简体   繁体   English

为什么 Throwable.getCause 在返回 `null` 之前检查 'cause' 是否是 'this' 而不是直接返回 cause?

[英]Why does Throwable.getCause check to see if 'cause' is 'this' before returning `null` instead of just returning the cause directly?

I had a reason to go into the source code for Throwable.getCause today and was a little surprised to see this code in that method:今天我有理由进入Throwable.getCause的源代码,并且在该方法中看到此代码时有点惊讶:

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

This is from Java 1.8, but it looks the same in the later versions I've looked at.这是来自 Java 1.8,但在我看过的更高版本中看起来相同。

My question is: why not simply return cause and be done with it?我的问题是:为什么不简单地return cause并完成它?

It isn't comparing cause to null , it's comparing cause to this .它不是将causenull进行比较,而是将causethis进行比较。 To avoid circles, if cause is this , it returns null.为避免循环,如果causethis ,则返回 null。

The code:编码:

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

Says if the cause is this return null otherwise return cause (which may also be null as it happens.说如果causethis返回null否则返回cause (它也可能是null因为它发生。

The story starts with this: private Throwable cause = this;故事是这样开始的: private Throwable cause = this; which is I believe the same in all versions >=1.4.我相信所有版本>=1.4 都是一样的。 That initialises the cause to being this object!这将原因初始化为这个对象!

The intention is that Throwable objects are immutable but it provides a method void initCause(Throwable cause) that can only be called once to initialise the cause or cause initialised by a constructor.目的是Throwable对象是不可变的,但它提供了一个方法void initCause(Throwable cause)只能调用一次来初始化原因或由构造函数初始化的原因。

As the documentation explains that allows the chaining of causes to sub-classes added before cause was introduced that don't include it in one of their constructors.正如文档所解释的那样,允许将原因链接到在引入cause之前添加的子类,这些子类不包含在其构造函数之一中。

So the class somehow wants to know if initCause has been called and throws IllegalStateException if it has (my comments):因此,该类以某种方式想知道是否已调用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;
}

The class is using cause==this to indicate cause not set.该类使用cause==this来指示未设置cause It can't use cause==null because null is a valid value.它不能使用cause==null因为null是一个有效值。 So it uses the anomalous state of cause==this because actively setting cause to this is the illogical state of a self-caused exception.所以它使用了cause==this的异常状态,因为主动设置causethis是自引发异常的不合逻辑状态。

It works, sure.它确实有效。 But is it really a good idea?但这真的是个好主意吗? I'm saying not.我说不是。 It conflates the states of "cause not set" and "cause has been set and is set to null ".它将“原因未设置”和“原因已设置并设置为null ”的状态混为一谈。 A less contorted design just introduces a flag private boolean isCauseSet=false;一个不太扭曲的设计只是引入了一个标志private boolean isCauseSet=false; and setting it if initCause is ever called or a constructor that sets it is called.并在initCause被调用或设置它的构造函数被调用时设置它。

The convoluted code we see in Throwable achieves nothing more than avoiding a boolean .我们在Throwable看到的复杂代码只不过是避免了boolean Saving a single boolean field inside Throwable really doesn't seem worth the bother.Throwable保存单个boolean字段似乎真的不值得打扰。 No useful application will ever have so many Throwable objects in circulation for it to matter.没有任何有用的应用程序会在流通中拥有如此多的Throwable对象,因此它很重要。

null值由printStackTrace方法使用, 例如,在调用stackTraceString方法时,第 421..450行标识堆栈跟踪的输出应何时完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 可抛出的 getCause 返回 null - Throwable getCause returns null 为什么从float返回方法返回double不会导致c ++中的任何错误/警告 - Why returning double from float returning method does not cause any error/warning in c++ 尝试查找异常源时,Exception.getCause() 返回 null - Exception.getCause() returning null when trying to find the source of an exception Java 什么是可抛出的原因? - Java what is a throwable cause? 为什么这会导致空指针异常? - Why does this cause a null pointer exception? EJBException为什么不使用Throwable.cause? - Why doesn't EJBException use Throwable.cause? 为什么此代码会导致堆栈溢出? 为什么只将== 1更改为&lt;2,然后起作用? - Why does this code cause a stack overflow? And why just change ==1 to <2, and then it works? 为什么不能使用可抛出的原因构造IllegalArgumentException(JDK 1.4.2)? - Why IllegalArgumentException (JDK 1.4.2) cannot be constructed with a throwable cause? 为什么 Throwable::printStackTrace 持有 PrintStream 的锁并导致 logback 死锁 - Why Throwable::printStackTrace holding lock of PrintStream and cause deadlock of logback 如果在异常上调用getCause(),为什么还要处理Throwable - Why do I have to deal with Throwable if I invoke getCause() on an Exception
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM