Java 为什么我不能在创建实例或引发异常时调用initCause()

Java 为什么我不能在创建实例或引发异常时调用initCause(),java,exception-handling,Java,Exception Handling,我不明白为什么我不能在创建实例或抛出异常的同一行中使用initCause()。如果我把它放在同一行,编译器认为该方法必须抛出一个可丢弃的对象 // All exceptions in the example are subclass of Exception class; private static void throwException() throws BadCodeException { throw new BadCodeException("Actual cause"); }

我不明白为什么我不能在创建实例或抛出异常的同一行中使用
initCause()
。如果我把它放在同一行,编译器认为该方法必须抛出一个可丢弃的对象

// All exceptions in the example are subclass of Exception class;
private static void throwException() throws BadCodeException {
    throw new BadCodeException("Actual cause");
}

private static void rethrowException() throws BadProgramException{
    try {
        throwException();
    } catch (BadCodeException e) {
        BadProgramException ex = new BadProgramException("Problem that occurred");
        ex.initCause(e);
        throw ex;
    } /* catch (BadCodeException e) { // Compiler tells about unhandled Throwable;
        throw new BadProgramException("Problem that occurred").initCause(e);
    } */

另外,如果有人告诉我链式异常的用法正确与否,我会很高兴,因为这只是我发现的。

正如khelwood所说,
initCause
有一个声明的返回类型
Throwable
(查看API文档)。因此,如果您抛出
initCause
的结果,那么(据编译器所知),您的方法可能抛出任何类型的
Throwable

要回答您的另一个问题,执行链接异常的正常方法是

throw new BadProgramException("Problem that occurred", e);
然后向
BadProgramException
添加另一个构造函数,如果它没有这样的构造函数,它只需使用两个参数调用
super


这种方法没有这个问题。如果
BadProgramException
是一个遗留类,您无法修改它来添加额外的构造函数,那么只需要调用
initCause

正如khelwood所说,
initCause
具有声明的返回类型
Throwable
(请查看API文档)。因此,如果您抛出
initCause
的结果,那么(据编译器所知),您的方法可能抛出任何类型的
Throwable

要回答您的另一个问题,执行链接异常的正常方法是

throw new BadProgramException("Problem that occurred", e);
然后向
BadProgramException
添加另一个构造函数,如果它没有这样的构造函数,它只需使用两个参数调用
super


这种方法没有这个问题。如果
BadProgramException
是一个旧类,您无法修改它来添加额外的构造函数,则只需调用
initCause

,因为这是签名:

public synchronized Throwable initCause(Throwable cause);
正如您所看到的,这里的返回类型是Throwable

在一行中执行此操作等于:

// Throwable is not BadProgramException! It's wider type
private static void rethrowException() throws BadProgramException {
    try {
        throwException();
    } catch (BadCodeException e) {
        BadProgramException ex = new BadProgramException("Problem that occurred");
        Throwable throwable = ex.initCause(e);
        throw throwable;
    }
}
需要额外处理的内容。您可以在一行中更改引用类型。您的方法不再抛出
BadProgramException
。它抛出了更宽的,这是最常见的异常类型

在一行中执行此操作不会更改引用类型:

private static void rethrowException() throws BadProgramException {
    try {
        throwException();
    } catch (BadCodeException e) {
        BadProgramException ex = new BadProgramException("Problem that occurred");
        ex.initCause(e);
        throw ex; // Reference type is still BadProgramException and matches current signature
    }
}
基本上,一个电话可以解决如下问题:

private static void rethrowException() throws Throwable {
    try {
        throwException();
    } catch (BadCodeException e) {
        BadProgramException ex = new BadProgramException("Problem that occurred");
        throw ex.initCause(e);
    }
}

但这并不是抛出所有错误的超类的好方法,比如
Throwable
。您需要抛出最窄的异常类型

因为这是签名:

public synchronized Throwable initCause(Throwable cause);
正如您所看到的,这里的返回类型是Throwable

在一行中执行此操作等于:

// Throwable is not BadProgramException! It's wider type
private static void rethrowException() throws BadProgramException {
    try {
        throwException();
    } catch (BadCodeException e) {
        BadProgramException ex = new BadProgramException("Problem that occurred");
        Throwable throwable = ex.initCause(e);
        throw throwable;
    }
}
需要额外处理的内容。您可以在一行中更改引用类型。您的方法不再抛出
BadProgramException
。它抛出了更宽的,这是最常见的异常类型

在一行中执行此操作不会更改引用类型:

private static void rethrowException() throws BadProgramException {
    try {
        throwException();
    } catch (BadCodeException e) {
        BadProgramException ex = new BadProgramException("Problem that occurred");
        ex.initCause(e);
        throw ex; // Reference type is still BadProgramException and matches current signature
    }
}
基本上,一个电话可以解决如下问题:

private static void rethrowException() throws Throwable {
    try {
        throwException();
    } catch (BadCodeException e) {
        BadProgramException ex = new BadProgramException("Problem that occurred");
        throw ex.initCause(e);
    }
}

但这并不是抛出所有错误的超类的好方法,比如
Throwable
。您需要抛出最窄的异常类型

我不太明白。您看到(或没有看到)什么错误?
initCause
具有返回类型
Throwable
。因此,如果您
抛出
initCause
的结果,那么(据编译器所知),您的方法可能抛出任何类型的
Throwable
错误:(33,13)java:unreported exception java.lang.Throwable;必须被抓住或宣布被扔出去,我不知道我是否明白。您看到(或没有看到)什么错误?
initCause
具有返回类型
Throwable
。因此,如果您
抛出
initCause
的结果,那么(据编译器所知),您的方法可能抛出任何类型的
Throwable
错误:(33,13)java:unreported exception java.lang.Throwable;必须被抓住或宣布被扔出去,@khelwood收到了。