Java 如果其中一个子方法引发异常,则跳过代码执行的最佳设计模式

Java 如果其中一个子方法引发异常,则跳过代码执行的最佳设计模式,java,design-patterns,Java,Design Patterns,我正在使用CoreJava开发一个测试框架。在我的应用程序中,我有一个父方法,它调用十个不同的子方法,每个方法都可以抛出自己的异常。要求是提供有关父方法执行的详细日志信息,其中包含执行该方法所花费的总时间、执行每个子方法所花费的时间、记录任何异常等信息。为此,我使用了多个try-catch-finally块 我的问题是,如果一个子方法抛出异常,那么跳过其余子方法执行的最佳方法是什么?例如:如果方法4抛出一个异常,我想记录该异常,并转到末尾,记录父方法在此之前所花费的时间 我尝试在父方法开始时使用

我正在使用CoreJava开发一个测试框架。在我的应用程序中,我有一个父方法,它调用十个不同的子方法,每个方法都可以抛出自己的异常。要求是提供有关父方法执行的详细日志信息,其中包含执行该方法所花费的总时间、执行每个子方法所花费的时间、记录任何异常等信息。为此,我使用了多个try-catch-finally块

我的问题是,如果一个子方法抛出异常,那么跳过其余子方法执行的最佳方法是什么?例如:如果方法4抛出一个异常,我想记录该异常,并转到末尾,记录父方法在此之前所花费的时间

我尝试在父方法开始时使用布尔变量将其初始化为true。在执行每个子方法之前,我检查布尔变量是否为true。每当抛出异常时,我都将布尔变量标记为false

我的伪代码如下所示:

public String parentMethod(){
    boolean execute = true;
    if(execute) {
        try event1; 
        catch(Event1Exception e1)  
            log e1; execute = false; 
        finally log event 1 time taken;
    }
    if(execute) {
        try event2; 
        catch(Event1Exception e2)  
            log e2; execute = false; 
        finally log event 2 time taken;
    }
    and so on ....
    log total time taken;
try {
  SomeT t = runTimed(() -> return foo());
} catch (ExceptionA a) ...

在我的实际代码中,我有大约十个不同的事件抛出它们自己的异常,有时不止一个。使用这种方法,为捕获的每个异常分配execute=false,然后再次检查execute的值似乎很笨拙。在不使用任何附加插件的情况下,还有比这更好的方法吗?

您好,我建议在单个try块中使用方法调用。在此try块末尾写入所有包含不同异常的catch块。每当任何方法抛出异常时,控件将直接转到相应的catch块,跳过其余的方法调用

例如:

try
{
    method1(); // Exception1 occured
    method2(); // skipped
    method3(); // skipped
}
catch(Exception1 e)
{
    // control goes here
    // End timer 

    // Calculate difference
    // Store difference in global variable
}
catch(Exception2 e)
{
}
catch(Exception3 e)
{
}

method1()
{
    // start timer

    // your code

    // End timer, if no exception occurred
    // Store difference in global variable
}

希望这会有所帮助。:-)

您好,我建议在单个try块中使用方法调用。在此try块末尾写入所有包含不同异常的catch块。每当任何方法抛出异常时,控件将直接转到相应的catch块,跳过其余的方法调用

例如:

try
{
    method1(); // Exception1 occured
    method2(); // skipped
    method3(); // skipped
}
catch(Exception1 e)
{
    // control goes here
    // End timer 

    // Calculate difference
    // Store difference in global variable
}
catch(Exception2 e)
{
}
catch(Exception3 e)
{
}

method1()
{
    // start timer

    // your code

    // End timer, if no exception occurred
    // Store difference in global variable
}

希望这会有所帮助。:-)

如果您只对第一个异常感兴趣,那么您可以在一个try-catch块中执行所有事件,并处理catch块中抛出的任何异常

try {
    event1();
    event2();
    // etc
} catch(Exception e) {
    //Handle
}

否则,为每个进程启动一个线程,并通过在一个线程出现故障时立即终止所有其他线程来处理故障。

如果您只对第一个异常感兴趣,则可以在一个try-catch块中执行所有事件,并处理catch块中引发的任何异常

try {
    event1();
    event2();
    // etc
} catch(Exception e) {
    //Handle
}

否则,为每个进程启动一个线程,并通过在一个线程出现故障时立即终止所有其他线程来处理故障。

看起来您有点思考过度了。试着抓住建筑已经给你你想要的。考虑这一点:

try {
     method1();
     method2();
     method3();
     method4();
 } catch(Exception e) {
   //do error hanlig here (log it for example)
 }  

在这种情况下,假设方法1和2成功执行,并且
method3
抛出异常-控件将转到catch块,而
method4
不执行。如果我没有正确理解你,这正是你需要的

看起来你有点想得太多了。试着抓住建筑已经给你你想要的。考虑这一点:

try {
     method1();
     method2();
     method3();
     method4();
 } catch(Exception e) {
   //do error hanlig here (log it for example)
 }  

在这种情况下,假设方法1和2成功执行,并且
method3
抛出异常-控件将转到catch块,而
method4
不执行。如果我对您的理解正确,这正是您所需要的

您只需记录异常并重新播放它:

public String parentMethod(){
    try {
        try {
            ... 
        } catch(Event1Exception e1) { 
            log e1;
            throw e1;
        } finally {
            log event 1 time taken;
        }

        try {
            ... 
        } catch(Event2Exception e2) { 
            log e2;
            throw e2;
        } finally {
            log event 2 time taken;
        }

    } catch (Event1Exception | Event2Exception | ... e) {
        // Can be safely ignored
    }
}
或者,如果您不想单独处理每个异常,您可以执行以下操作:

public String parentMethod(){
    try {
        try {
            ... 
        } finally {
            log event 1 time taken;
        }

        try {
            ... 
        } finally {
            log event 2 time taken;
        }

    } catch (Event1Exception | Event2Exception | ... e) {
        log e
    }
}

您可以只记录异常并重新播放它:

public String parentMethod(){
    try {
        try {
            ... 
        } catch(Event1Exception e1) { 
            log e1;
            throw e1;
        } finally {
            log event 1 time taken;
        }

        try {
            ... 
        } catch(Event2Exception e2) { 
            log e2;
            throw e2;
        } finally {
            log event 2 time taken;
        }

    } catch (Event1Exception | Event2Exception | ... e) {
        // Can be safely ignored
    }
}
或者,如果您不想单独处理每个异常,您可以执行以下操作:

public String parentMethod(){
    try {
        try {
            ... 
        } finally {
            log event 1 time taken;
        }

        try {
            ... 
        } finally {
            log event 2 time taken;
        }

    } catch (Event1Exception | Event2Exception | ... e) {
        log e
    }
}

这里没有答案:不要那样做

听起来你只是违反了单一责任原则。一个类/方法应该有一个目的,并且只有一个目的

意思:你必须调用10种不同的方法,这已经很可疑了——在一个如此复杂的环境中,你认为值得在这里提出一个问题

因此,我的建议是退一步,看看是否可以重新考虑代码库,以减少不同的方法调用捆绑在一起

当您确实无法避免调用10个方法时,只需使用multicatch:

 try {
   foo();
   bar();
   ...
 } catch (ExceptionA | ExceptionB | ...
除此之外,您肯定应该致力于防止代码重复。我想到了这样的事情:

private interface CallContext<T, X extends Throwable> {
  T execute() throws X;
}

private static <T, X extends Throwable> T runTimed(CallContext<T, X> context) throws X {
     prepare timer
     T result = context.execute();
     put timed value somewhere
     return result;
}

这里没有答案:不要那样做

听起来你只是违反了单一责任原则。一个类/方法应该有一个目的,并且只有一个目的

意思:你必须调用10种不同的方法,这已经很可疑了——在一个如此复杂的环境中,你认为值得在这里提出一个问题

因此,我的建议是退一步,看看是否可以重新考虑代码库,以减少不同的方法调用捆绑在一起

当您确实无法避免调用10个方法时,只需使用multicatch:

 try {
   foo();
   bar();
   ...
 } catch (ExceptionA | ExceptionB | ...
除此之外,您肯定应该致力于防止代码重复。我想到了这样的事情:

private interface CallContext<T, X extends Throwable> {
  T execute() throws X;
}

private static <T, X extends Throwable> T runTimed(CallContext<T, X> context) throws X {
     prepare timer
     T result = context.execute();
     put timed value somewhere
     return result;
}

如果你有类似于(…){try{execute}catch{handle exception}}的东西,那么你可以很容易地做到:
try{for(…){execute}catch{handle exception}}
如果你有类似于(…){try{execute catch{handle exception}}的东西,那么你可以很容易做到:
try{for(…){execute}catch{handle exception}}
。当一个简单的try-catch块提供了完美的解决方案时,这太复杂了。这个问题一个try-catch会让你不记录每个事件的时间呃,为什么是downvoting?我在评论中说了为什么我认为它应该是downvoting,但我知道