Java try-catch-finally块中的递归:如何在原始函数调用中只调用finally块一次?

Java try-catch-finally块中的递归:如何在原始函数调用中只调用finally块一次?,java,recursion,try-catch-finally,Java,Recursion,Try Catch Finally,假设我有一个名为foo()的函数。在foo()中有一个try-catch-finally块。在catch块内部,递归调用foo() 我的问题是: 如何使finally块在原始函数调用中只执行一次? 我想通过简单地使用计数器(一个我递增的整数)来限制递归调用的数量。请参阅下面的示例代码,您将对我试图实现的目标有一个大致的了解: private Integer recursion_counter = 0; public ReturnType foo(){ ReturnType return

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

我的问题是:

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

我想通过简单地使用计数器(一个我递增的整数)来限制递归调用的数量。请参阅下面的示例代码,您将对我试图实现的目标有一个大致的了解:

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块可能会被多次调用,这是我不希望发生的


如果您认为有更好的方法来实现这一点(例如,使用非递增整数等),请分享您的想法。

最初,必须从该方法外部调用方法
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();
    }
}

最初,方法
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();
    }
}

一种简单的方法是:将attemptNumber作为foo的额外参数,而不是recursioncount的成员变量,默认值为1。(从技术上讲,重载函数,因为Java不提供默认参数)


我认为将此信息与函数调用一起携带比将其保持为实例状态更有意义。顺便说一句,这不是线程安全的。一种简单的方法是:使用attemptNumber作为foo的额外参数,而不是recursioncount的成员变量,默认值为1。(从技术上讲,重载函数,因为Java不提供默认参数)


我认为将此信息与函数调用一起携带比将其保持为实例状态更有意义——这不是线程安全的,顺便说一句,不要对此类任务使用递归:

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();
            }
        }
    }
}
为了完整起见,如果要通过递归解决任务,请不要使用实例字段来保存递归的局部状态。当您保持本地状态时,不存在需要重置的持久状态。(顺便说一下,如果
int
值足够,则不要使用
Integer
对象)


不要对这样的任务使用递归:

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();
            }
        }
    }
}
为了完整起见,如果要通过递归解决任务,请不要使用实例字段来保存递归的局部状态。当您保持本地状态时,不存在需要重置的持久状态。(顺便说一下,如果
int
值足够,则不要使用
Integer
对象)


每次输入
try
块时,也必须输入
finally
块。是时候重新考虑你的设计了。这看起来像是一个;您希望将某项内容限制为五次重新尝试。使用普通循环。不需要递归。另外,Netflix是实现这一点的更好的方法(imo)。感谢您到目前为止的想法。在另一个函数中“包装”foo()怎么样。我们称之为wrappedFoo()。它只调用原始的foo(),然后在foo()返回后,我可以在wrappedFoo()函数中调用resetRecursionCounter()。我还需要将resetRecursionCounter()放在catch块if语句中。我认为这会起作用,尽管我不确定是否会反对。每次输入
try
块时,也必须输入
finally
块。是时候重新考虑你的设计了。这看起来像是一个;您希望将某项内容限制为五次重新尝试。使用普通循环。不需要递归。另外,Netflix是实现这一点的更好的方法(imo)。感谢您到目前为止的想法。在另一个函数中“包装”foo()怎么样。我们称之为wrappedFoo()。它只调用原始的foo(),然后在foo()返回后,我可以在wrappedFoo()函数中调用resetRecursionCounter()。我还需要将resetRecursionCounter()放在catch块if语句中。我认为这会起作用,尽管我不确定它是否会受到反对。这是真的,但如果在许多地方调用foo(),那么在每个调用它的地方编写try-catch就很不方便了。这是一个很好的备份解决方案,但我正试图最大限度地发挥我的惰性。:)如果在许多地方调用了
FileInputStream
构造函数,那么处理它抛出的
FileNotFoundException
是否不方便?一般观点:如果可以在一个地方而不是在多个地方处理异常,那么是的,我想说,使用在多个地方处理异常的解决方案是不方便的。否则,如果它不能在一个地方处理,那么它并不不方便,因为这是您唯一的选择。我认为您的问题的答案取决于上下文。这是真的,但是如果在许多地方调用foo(),那么在每个调用的地方编写try-catch是非常不方便的。这是一个很好的备份解决方案,但我正试图最大限度地发挥我的惰性。:)如果在许多地方调用了
FileInputStream
构造函数,那么处理它抛出的
FileNotFoundException
是否不方便?一般观点:如果可以在一个地方而不是在多个地方处理异常,那么是的,我想说,使用在多个地方处理异常的解决方案是不方便的。否则,如果它不能在一个地方处理,那么它并不不方便,因为这是您唯一的选择。我认为你问题的答案取决于上下文。