为什么一个方法在catch中需要return语句,即使catch是重新抛出异常

时间:2016-06-10 11:54:49

标签: java exception-handling

我编写了一个在try语句中返回一些值的方法。在catch中我调用handleException,它将具有理解异常和重新抛出新异常的转换逻辑。这里handleException总是抛出异常,仍然是getXYZ()给出了返回语句的编译时错误。我没有处理异常,我只是抛出新异常,为什么该方法需要return语句。

public String getXYZ(String input) {
    try {
        return getFromDAO(input);
    } catch (Exception e) {
        handleException(e);
    }
}
private void handleException(Exception e) {
    try {
        throw e;
    } catch(SomeException se) {
        throw new MyRuntimeException("MyException message", se);
    } catch(SomeOtherException soe) {
        throw new MyRuntimeException("MyException message", soe);
    }
}

此方法的其他版本编译。

public String getXYZ(String input) {
    try {
        return getFromDAO(input);
    } catch (Exception e) {
        throw e;
    }
}

4 个答案:

答案 0 :(得分:4)

你没有在catch块中抛出任何东西,你正在调用你的句柄函数,最终会导致抛出一个新的异常,但getXYZ中的实际代码正在执行一个函数致电catch。如果您将handleException更改为以后在某些情况下不会抛出异常,那么getXYZ会返回什么呢?

答案 1 :(得分:1)

解决此问题的一种方法是让编译器清楚地知道您希望抛出异常。

public String getXYZ(String input) {
    try {
        return getFromDAO(input);
    } catch (Exception e) {
        throw handleException(e); // compiles ok.
    }
}

private RuntimeException handleException(Exception e) {
    try {
        throw e;
    } catch(SomeException se) {
        return new MyRuntimeException("MyException message", se);
    } catch(SomeOtherException soe) {
        return new MyRuntimeException("MyException message", soe);
    } catch(RuntimeException re) {
        return re;
    } catch(Exception e2) {
        return new MyRuntimeException("MyException message", e2);
    }
}

BTW另一种方法是根本不包装Exception并保留异常。

public String getXYZ(String input) {
    try {
        return getFromDAO(input);
    } catch (Exception e) {
        throw rethrow(e); // compiles ok.
    }
}

/**
 * Cast a CheckedException as an unchecked one.
 *
 * @param throwable to cast
 * @param <T>       the type of the Throwable
 * @return this method will never return a Throwable instance, it will just throw it.
 * @throws T the throwable as an unchecked throwable
 */
@SuppressWarnings("unchecked")
public static <T extends Throwable> RuntimeException rethrow(Throwable throwable) throws T {
    throw (T) throwable; // rely on vacuous cast
}

答案 2 :(得分:1)

您可能还想考虑使用新的java 8 lambda功能来解决您的问题。您必须创建一个函数接口来声明lambdas的签名(具有相关的例外)。您的handleException方法现在将是运行lambda并处理异常的方法。

public String getXYZ(String input) {
    return handleKnownExceptions(() -> getFromDAO(input));
}

private <T> T handleKnownExceptions(ThrowingCode<T> throwingCode)
{
    try {
        return throwingCode.get();
    } catch(SomeException se) {
        throw new MyRuntimeException("MyException message", se);
    } catch(SomeOtherException soe) {
        throw new MyRuntimeException("MyException message", soe);
    }
}

@FunctionalInterface
public interface ThrowingCode<T>
{
    T get() throws SomeException, SomeOtherException;
}

答案 3 :(得分:0)

有一种模式,我已经看过几次来处理这种情况。您让handleException方法声明它返回一个异常。这只是指示性的,它永远不会返回任何东西,它总会抛出,就像以前一样。声明的返回类型将允许调用者使用throw handleException()语句,这将使编译器满意。结果代码为:

public String getXYZ(String input) throws Exception {
    try {
        return getFromDAO(input);
    } catch (Exception e) {
        throw handleException(e);
    }
}

/**
 * This method will never return normally, always throws. 
 */
private Exception handleException(Exception e) throws Exception
{
    try {
        throw e;
    } catch(SomeException se) {
        throw new MyRuntimeException("MyException message", se);
    } catch(SomeOtherException soe) {
        throw new MyRuntimeException("MyException message", soe);
    }
}