1: Function description
When we try to live in a certain block of code after an exception occurs, we hope to throw a new exception in the catch, but we don't want to lose the original exception that caused the exception, we can use this method to set the original exception to our new exception.
2: Example
2.1: Define the original exception
public class OriginException extends Exception {
public OriginException() {
}
public OriginException(String message) {
super(message);
}
}
2.2: The definition method throws the original exception
public void testA() throws OriginException {
throw new OriginException("我是原始异常");
}
2.3: Define a new exception
public class NewException extends Exception {
public NewException() {
}
public NewException(String message) {
super(message);
}
}
2.4: Define the method to throw a new exception
public void testB() throws NewException {
try {
this.testA();
} catch (OriginException e) {
NewException newException = new NewException("我是新throw的异常");
// 设置原始异常
newException.initCause(e);
throw newException;
}
}
2.5: Test code
public static void main(String[] args) {
try {
new InitCauseTest().testB();
} catch (NewException e) {
System.out.println("新的异常信息是:" + e.getMessage());
Throwable cause = e.getCause();
System.out.println("原始的异常信息是:" + cause.getMessage());
}
}
run:
新的异常信息是:我是新throw的异常
原始的异常信息是:我是原始异常
2.6: Complete test code
public class InitCauseTest {
public void testA() throws OriginException {
throw new OriginException("我是原始异常");
}
public void testB() throws NewException {
try {
this.testA();
} catch (OriginException e) {
NewException newException = new NewException("我是新throw的异常");
// 设置原始异常
newException.initCause(e);
throw newException;
}
}
public static void main(String[] args) {
try {
new InitCauseTest().testB();
} catch (NewException e) {
System.out.println("新的异常信息是:" + e.getMessage());
Throwable cause = e.getCause();
System.out.println("原始的异常信息是:" + cause.getMessage());
}
}
}
3: Analysis
The source code of the initCause method is as follows:
java.lang.Throwable#initCause
public synchronized Throwable initCause(Throwable cause) {
// <2021-02-26 18:18>
if (this.cause != this)
throw new IllegalStateException("Can't overwrite cause with " +
Objects.toString(cause, "a null"), this);
// 不允许将自己设置为引起异常
if (cause == this)
throw new IllegalArgumentException("Self-causation not permitted", this);
// 设置引起异常的异常
this.cause = cause;
return this;
}
You can see that the method is defined in the class java.lang.Throwable
, and the final execution code this.cause = cause
sets the original exception information that caused the exception. <2021-02-26 18:18>
The code, this.cause
after the exception object is initialized, is this, that is, the definition private Throwable cause = this;
, that is, the default value is this, debug verification is as follows: at
this time, if the getCause
method is called, it will return null. The source code is as follows:
java.lang.Throwable#getCause
public synchronized Throwable getCause() {
return (cause==this ? null : cause);
}
<2021-02-26 18:18>
Another function of the code is to allow the setting to cause an exception only once. I think this should be based on security considerations to prevent accidental or deliberate tampering. initCause
Exceptions will occur after multiple calls . The call test is as follows: