从循环中调用的方法中断出for循环

时间:2017-04-12 05:46:00

标签: java loops for-loop iteration break

我有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执行所需的样板代码并以可读方式巧妙地将它们打包

5 个答案:

答案 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();
}

errorMessagesMap<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();
    }
}