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

时间:2018-04-26 14:37:26

标签: java exception-handling

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

// 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);
    } */

另外,如果有人告诉我是否正确使用链式异常,我会很高兴,因为只有我找到了。

2 个答案:

答案 0 :(得分:3)

因为这是签名:

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这样的所有错误的超类的好方法。您需要抛出最窄的异常类型。

答案 1 :(得分:1)

正如khelwood所述,initCause的声明返回类型为Throwable(请查看API文档)。因此,如果你抛出initCause的结果,那么(就编译器而言),你的方法可能抛出任何类型的Throwable

要回答您的其他问题,执行链式异常的常规方法是

throw new BadProgramException("Problem that occurred", e);

然后将另一个构造函数添加到BadProgramException,如果它没有这样的构造函数,只需用它的两个参数调用super

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