Try-catch是用来帮助异常处理的。这意味着它将在某种程度上帮助我们的系统变得更加健壮:尝试从意外事件中恢复。
我们怀疑在执行和指令(发送消息)时可能会发生一些事情,因此它被包含在try中。如果发生了几乎意想不到的事情,我们可以做些什么:我们编写捕获。我不认为我们调用只是为了记录异常。我认为catch块是为了给我们从错误中恢复的机会。
现在,假设我们从错误中恢复,因为我们可以修复错误。如果能再试一次,那就太好了:
try{ some_instruction(); }
catch (NearlyUnexpectedException e){
fix_the_problem();
retry;
}
这将很快陷入永恒循环,但让我们假设fix_the_problem返回true,然后重试。假设在Java中没有这样的东西,你将如何解决这个问题?你认为解决这个问题的最佳设计代码是什么?
这就像一个哲学问题,因为我已经知道Java不直接支持我所要求的内容。
https://onlinegdb.com/a-7RsL1Gh
public void doSomething() throws Exception{
final int MAX_TRIES = 10;
int count = 0;
while(count++ < MAX_TRIES){
try{
System.out.println("trying");
causeIssue(count); // throws error/exception till count 2
System.out.println("trying successful");
break; // break on success
} catch (Exception e){
System.out.println("caught, logging Exception:" + count);
} catch (Error e){
System.out.println("caught, logging Error:" + count);
}
}
}
输出:
trying
caught, logging Error:1
trying
caught, logging Error:2
trying
trying successful
强制性的“企业级”解决方案:
public abstract class Operation {
abstract public void doIt();
public void handleException(Exception cause) {
//default impl: do nothing, log the exception, etc.
}
}
public class OperationHelper {
public static void doWithRetry(int maxAttempts, Operation operation) {
for (int count = 0; count < maxAttempts; count++) {
try {
operation.doIt();
count = maxAttempts; //don't retry
} catch (Exception e) {
operation.handleException(e);
}
}
}
}
并呼吁:
OperationHelper.doWithRetry(5, new Operation() {
@Override public void doIt() {
//do some stuff
}
@Override public void handleException(Exception cause) {
//recover from the Exception
}
});
生产就绪代码:
@FunctionalInterface
public interface Operation {
void doCall() throws IOException;
default void handleException(Exception e) {
//Your custom default implementation
}
public class OperationHelper {
public static void doWithRetry(int maxAttempts, Operation operation) {
for (int count = 0; count <= maxAttempts; count++) {
try {
operation.doCall();
return;
} catch (Exception e) {
if (count == maxAttempts) {
e.printStackTrace();
return;
} else {
operation.handleException(e);
}
}
}
}
}
在代码中使用默认实现:
OperationHelper.doWithRetry(10,
() -> //do your job );
当需要自定义异常句柄时使用:
OperationHelper.doWithRetry(10, new Operation() {
@Override public void doIt() {
//do some stuff
}
@Override public void handleException(Exception cause) {
//recover from the Exception
}
});
如果不是所有异常都需要重试,那么只有一些例外。如果至少要尝试一次,这里有一个替代的实用方法:
void runWithRetry(Runnable runnable, Class<Exception> exClass, int maxRetries) {
Exception err = null;
do {
maxRetries--;
try {
runnable.run();
err = null;
} catch (Exception e) {
if(exClass.isAssignableFrom(e.getClass())){
err = e;
}else {
throw e;
}
}
} while (err != null && maxRetries > 0);
if (err != null) {
throw err;
}
}
用法:
runWithRetry(() -> {
// do something
}, TimeoutException.class, 5)