我有List
jobs
,需要x个步骤(比如5)。每个步骤都必须成功才能继续,如果任何步骤失败,则必须提出一个票证并且必须取消当前job
的执行并继续下一个job
。
这就是我现在所拥有的(它就像一个魅力)。
for(Job aJob: jobs){
// Step 1
try{
Obj objRet1 = method1();
// use objRet1;
}
catch(Exception e){
raiseTicket(errMsg1,e);
break;
}
// Step 2
try{
Obj objRet2 = method2();
// use objRet2;
}
catch(Exception e){
raiseTicket(errMsg2,e);
break;
}
// Step 3
try{
Obj objRet3 = method3();
// use objRet3;
}
catch(Exception e){
raiseTicket(errMsg3,e);
break;
}
...
// Step 5
}
这不是很优雅,易读,IMO。我想将它浓缩成类似下面的东西。
for(Job aJob: jobs){
step1();
step2();
..
step5();
}
step1(){
try{
...
}
catch(Exception e){
raiseTicket(errMsg1,e);
break;
}
}
step2(){
}
...
有人可以说明如何改进这个程序吗?请注意,返回一个值或将其存储在方法参数中也可能不起作用,因为,我在此尝试实现的是避免break
执行所需的样板代码并以可读方式巧妙地将它们打包
答案 0 :(得分:1)
首先,break
不会中断当前迭代但会中断整个循环。您需要使用continue
来实现这一目标。但是,由于抛出的异常将跳过剩余的步骤,在这种情况下,您不需要任何额外的声明。
为什么不使用这样的东西?
// create list with errorMessages in the following order: errMesFor1, errMesFor2,..., errMesFor5
List<String> messageList = new ArrayList<>();
messageList.add(errMesFor1);
messageList.add(errMesFor2);
messageList.add(errMesFor3);
messageList.add(errMesFor4);
messageList.add(errMesFor5);
for(Job aJob: jobs){
// create list that holds successfully created objects
List<Obj> objList = new ArrayList<>();
try {
Obj objRet1 = method1();
// use objRet1;
list.add(objRet1);
Obj objRet2 = method2();
// use objRet2;
list.add(objRet2);
Obj objRet3 = method3();
// use objRet3;
list.add(objRet3);
Obj objRet4 = method4();
// use objRet4;
list.add(objRet4);
Obj objRet5 = method5();
// use objRet5;
list.add(objRet5);
}
catch(Exception e){
// retrieve message for the first element that was not successfully added to the object list, hence the one that threw error
raiseTicket(messageList.get(objList.size()),e);
}
这样,您只需要编写一次try-catch
块。
在list
中整理邮件也很不错(或者您甚至可以在列表上编写自定义wrapper class
)。
唯一需要的是对象列表,以便您可以轻松找到引发异常的对象。
答案 1 :(得分:1)
如果发生错误,您可以在每个步骤中抛出一个已检查的异常,然后在for循环中捕获已检查的异常。像这样:
class StepException extends Exception {...}
for (Job aJob: jobs) {
try {
step1();
step2();
...
step5();
} catch (StepException se) {
// do something, e.g. print error to console
// the for loop will keep going when this occurs
}
}
step1() throws StepException {
try {
...
} catch (Exception e) {
raiseTicket(...);
throw new StepException(e);
}
}
// similar to step2(), ..., step5()
答案 2 :(得分:1)
一种可能的解决方案可能是:
for (Job job : jobs) {
AtomicInteger step = new AtomicInteger();
try {
Obj result = executeJob(step, () -> method1());
// do something with result
result = executeJob(step, () -> method2());
// do something with result
result = executeJob(step, () -> method3());
// do something with result
} catch (Exception e) {
raiseTicket(errorMessages.get(step.get()), e);
}
}
private Obj executeJob(AtomicInteger step, Supplier<Obj> supplier) {
step.incrementAndGet();
return supplier.get();
}
errorMessages
是Map<Integer, String>
。
答案 3 :(得分:0)
根据JAVA基础知识没有人可以使用外部循环或开关
由于方法代表堆栈内存条目,如果循环位于另一个堆栈条目中且方法位于其他堆栈条目中,则无法从堆栈内存中断循环。
答案 4 :(得分:0)
让步骤抛出一个特定的异常,让循环代码处理它!
使用以下异常类
class StepExecutionException extends RuntimeException {
StepExecutionException(String message, Throwable cause) {
super(message, cause);
}
void raiseTicket() {
// Code that raises the ticket ...
// The message can be retrieved with getMessage().
// The cause can be retrieved with getCause().
}
}
您可以使用该代码轻松实现这些步骤:
void step1() {
try {
...
} catch(Exception e) {
throw new StepExecutionException("Step 1", e);
}
}
现在您的循环代码如下:
for (Job aJob : jobs) {
try {
step1();
step2();
...
} catch (StepExecutionException see) {
see.raiseTicket();
}
}