我有代码(简化的假设示例):
public String handleEditRequest(...) {
if (isBadArg()) {
...
req.getSession().setAttribute("errorMessage", "...");
return "redirect:/product/edit" + id + "/.htm";
}
if (isEntityNotInDataBase()) {
...
req.getSession().setAttribute("errorMessage", "...");
return "redirect:/error.htm";
}
...
return "redirect:/product/show" + id + "/.htm";
}
现在我有责任为此代码添加SLA计时计算。如果我只有一个return语句,我只需将方法体包装在:
public String handleEditRequest(...) {
Timer timer = new Timer().start();
// ... CODE ...
slaService.send(timer.stop());
return "redirect:/product/show" + id + "/.htm";
}
但错误处理代码阻止了这样的解决方案。有很多种可能性。例如,添加:
timer.stop();
slaService.send(timer);
在任何return
声明之前。但这会导致代码重复。
或者使用try {} catch () {}
(Emacs Elisp经验给我启发):
private static class GotoError extends Throwable {}
public String handleEditRequest(...) {
Timer timer = new Timer().start();
String redirectUrl = "redirect:/product/show" + id + "/.htm";
try {
if (isBadArg()) {
...
req.getSession().setAttribute("errorMessage", "...");
redirectUrl = "redirect:/product/edit" + id + "/.htm";
throw new GotoError();
}
if (isEntityNotInDataBase()) {
...
req.getSession().setAttribute("errorMessage", "...");
redirectUrl = "redirect:/error.htm";
throw new GotoError();
}
...
} catch (GotoError e) { }
slaService.send(timer.stop());
return redirectUrl;
}
但是今天我重新思考并使用do { ... break; ... } while (false);
范例(在谷歌上搜索我发现while (true) {if () {break} .... break;}
示例,但我讨厌最后的中断声明!!):
public String handleEditRequest(...) {
Timer timer = new Timer().start();
String redirectUrl = "redirect:/product/show" + id + "/.htm";
do {
if (isBadArg()) {
...
req.getSession().setAttribute("errorMessage", "...");
redirectUrl = "redirect:/product/edit" + id + "/.htm";
break;
}
if (isEntityNotInDataBase()) {
...
req.getSession().setAttribute("errorMessage", "...");
redirectUrl = "redirect:/error.htm";
break;
}
...
} while (false);
slaService.send(timer.stop());
return redirectUrl;
}
在Java中的错误检查代码中使用什么构造来进行goto?我是否会错过一些自然解决问题的内置语言结构?
PS
C-like错误处理来自我在普通C中的10年,并允许使用线性代码。许多Java意大利面看起来像:
if (!bad1()) {
if (!bad2()) {
if (!bad3()) {
if (!bad4()) { ... }}}}
这可以写成:
if (bad1())
return errorCode;
if (bad2())
throw new Ex();
if (bad3())
return null;
if (bad4())
break;
// Now do job, all fine!
答案 0 :(得分:5)
将整个方法包装在另一个方法中:
public String handleEditRequest(...) {
Timer timer = new Timer().start();
try {
return handleEditRequestImpl(...);
} finally {
timer.stop();
slaService.send(timer);
}
}
private String handleEditRequestImpl(...) {
// Lots of code
}
如果handleEditRequest
正在实现一个接口,您甚至可以使用proxy自动计时该接口中方法的所有调用。 (代理将通过以相同的方式处理每个方法来实现接口:启动计时器,调用实际方法,停止计时器。)
(如其他地方所述,看起来您可能很可能将更多的错误处理集中在一起......)
答案 1 :(得分:2)
显而易见的事情是将所有错误代码放在一个单独的函数中,并使用return
来突破。您甚至可以转发状态或抛出异常。
我在Java中使用了do{...}while(false);
,但这是相当不合时宜的。