Reputation: 69
Let's say I have a function named foo(). Within foo() there is a try-catch-finally block. Inside the catch block, foo() is called recursively.
My question is:
How can I have the finally block only execute once, on the original function call?
I want to limit the number of recursive calls that can be made by simply using a counter (an Integer that I increment). Please see the example code below and you will have a generic understanding of what I am trying to accomplish:
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;
}
Unless I am mistaken, the finally block can potentially be called multiple times, which I do not want to happen.
If you believe there is a better way to accomplish this (e.g., using something other than an incrementing integer, etc.), then please share your thoughts.
Upvotes: 0
Views: 1856
Reputation: 298203
Simply don’t use recursion for such a task:
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();
}
}
}
}
Just for completeness, if you’re going to solve a task via recursion, don’t use instance fields to hold the local state of the recursion. When you keep local what is supposed to be local, there is no persistent state that needs a reset. (And, by the way, don’t use Integer
objects where int
values are sufficient)
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);
}
}
}
Upvotes: 2
Reputation: 4959
One simple way: instead of a member variable for recursioncount, make attemptNumber an extra argument to foo, with default=1. (Overloaded function technically, since Java doesn't do default parameters)
I think carrying this information along with the function call makes a bit more sense than keeping it as instance state-- which is not thread-safe BTW
Upvotes: 0
Reputation: 20914
Initially, method foo()
must be invoked from outside of that method. That's your initial call and that's where your try-catch
should be.
Pseudo code. Uncompiled and untested.
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();
}
}
Upvotes: 1