在try-catch-finally块中进行递归:如何仅在原始函数调用中一次调用finally块?

时间:2019-04-19 03:24:34

标签: java recursion try-catch-finally

假设我有一个名为foo()的函数。在foo()中有一个try-catch-finally块。在catch块内部,以递归方式调用foo()。

我的问题是:

如何在原始函数调用上使finally块仅执行一次?

我想限制仅通过使用计数器(我递增的Integer)可以进行的递归调用的数量。请查看下面的示例代码,您将对我要完成的工作有一个大致的了解:

private Integer recursion_counter = 0;

public ReturnType foo(){
    ReturnType returnType = new ReturnType();

    try{
        // Try to do something...
        returnType = doSomething();
    } catch (Exception e){
        if (recursion_counter == 5) {
            // Issue not fixed within 5 retries, throw the error
            throw e;
        } else {
            recursion_counter++;
            attemptToFixTheIssue();
            returnType = foo();
            return returnType;
        }
    } finally{
        resetRecursionCounter();
    }

    return returnType;
}

private void resetRecursionCounter(){
    recursion_counter = 0;
}

除非我弄错了,finally块可能会多次调用,而我不想发生这种情况。

如果您认为有更好的方法可以做到这一点(例如,使用除递增整数以外的方法等),请分享您的想法。

3 个答案:

答案 0 :(得分:2)

根本不对此类任务使用递归:

public ReturnType foo() {
    for(int attempts = 0; ; attempts++) {
        try {
            // Try to do something...
            return doSomething();
        } catch(Exception e) {
            if(attempts == 5) {
                // Issue not fixed within 5 retries, throw the error
                throw e;
            } else {
                attemptToFixTheIssue();
            }
        }
    }
}

为了完整起见,如果您要通过递归解决任务,请不要使用实例字段来保存递归的本地状态。当您将本地设置为本地时,没有需要重置的持久状态。 (而且,请不要使用Integer值足够的int对象)

public ReturnType foo() {
    return foo(0);
}

private ReturnType foo(int recursionCounter) {
    try {
        // Try to do something...
        return doSomething();
    } catch (Exception e){
        if (recursionCounter == 5) {
            // Issue not fixed within 5 retries, throw the error
            throw e;
        } else {
            attemptToFixTheIssue();
            return foo(recursionCounter + 1);
        }
    }
}

答案 1 :(得分:0)

最初,方法foo()必须从该方法外部调用。那是您的第一个电话,应该是您的try-catch所在的地方。

伪代码。未经编译且未经测试。

public static void main(String[] args) {
    try {
        ReturnType rt = foo();
    }
    catch (Exception e) {
    }
}

ReturnType foo() throws Exception {
    ReturnType returnType = new ReturnType();
    if (recursion_counter == 5) {
        throw new Exception();
    }
    else {
        foo();
    }
}

答案 2 :(得分:0)

一种简单的方法:将tryNumber用作foo的附加参数,而不是递归计数的成员变量,默认值为1。 (技术上重载了函数,因为Java不执行默认参数)

我认为将这些信息与函数调用一起携带比将其保留为实例状态更有意义-这不是线程安全的BTW