从循环内调用的方法中跳出 for 循环
Break out of for loop from a method called within loop
我有一个 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
执行所需的样板代码,并将它们整齐地打包在一个可读的方法中.
首先,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
)。
唯一需要的额外内容是对象列表,以便您可以轻松找到引发异常的对象。
你可以做的是,如果发生错误,在每个步骤中抛出一个已检查的异常,然后在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()
根据JAVA基础知识,没有人可以使用 break outside loop 或 switch
As Methods are represent stack memory entries you can't break loop from stack memory in case where loop is in another stack entry and method is in other stack entry.
让步骤抛出特定异常,让循环代码处理!
有以下例外情况class
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();
}
}
一个可能的解决方案是:
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>
。
我有一个 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
执行所需的样板代码,并将它们整齐地打包在一个可读的方法中.
首先,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
)。
唯一需要的额外内容是对象列表,以便您可以轻松找到引发异常的对象。
你可以做的是,如果发生错误,在每个步骤中抛出一个已检查的异常,然后在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()
根据JAVA基础知识,没有人可以使用 break outside loop 或 switch
As Methods are represent stack memory entries you can't break loop from stack memory in case where loop is in another stack entry and method is in other stack entry.
让步骤抛出特定异常,让循环代码处理!
有以下例外情况class
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();
}
}
一个可能的解决方案是:
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>
。