2012-10-11 89 views
2

我想这不一定是'正确的'答案,也许它更像是一个风格问题,但我经常发现自己想知道如何构建try/catch块。嵌套式或顺序异常处理?

例如,采用下面我假设的一段代码(纯粹是说明性的)中概述的两种方法,我有一种方法会抛出我多次调用的异常,但需要根据调用它的不同处理方式。同样,不同的处理程序可能会引发不同类型的异常。

private Object exceptionMethod() throws Exception { 
    throw new Exception("Something bad happened"); 
} 

public void useMethodSequentialHandlers() { 
    Object o1; // Must be declared in a wider scope than where it is used 
    try { 
     o1 = exceptionMethod(); 
    } catch (Exception ex) { 
     // Assume we cannot continue after this exception so we'll return or 
     // rethrow to exit the method 
     return; 
    } 

    Object o2; // Must be declared in a wider scope than where it is used 
    // Do something that requires o1 
    for (int i = 0; i < 100; i++) { 
     try { 
      o2 = exceptionMethod(); 
      // Here we would use the objects in some manner 
      boolean equal = o1.equals(o2);// Just a pointless example 
               // to show that both objects 
               // are required 
       // Assume the method does a load of stuff down here 
     } catch (Exception ex) { 
      // Assume we can continue to the next iteration after this exception 
      continue; 
     } 
    } 
} 

当我看到它有一个顺序的try/catch块的优点是,它是更清晰的读者正好在我回应异常哪一点因此,也许有更好的代码清晰。 缺点是我们在方法的各个地方散布了异常处理,而且我们的变量声明的范围比所需范围更广(这是一件坏事吗?)。

或者:

public void useMethodNestedHandlers() { 
    try { 
     Object o1 = exceptionMethod(); // Can be declared inside scope where it is used 
     // Do something that requires o1 
     for (int i = 0; i < 100; i++) { 
      try { 
       Object o2 = exceptionMethod(); // Can be declared inside scope where it is used 
       // Here we would use the objects in some manner 
       boolean equal = o1.equals(o2); // Just a pointless example 
               // to show that both objects 
               // are required 
       // Assume the method does a load of stuff down here 
      } catch (Exception ex) { 
       // Assume we can continue to the next iteration after this 
       // exception 
       continue; 
      } 
     } 
    } catch (Exception ex) { 
     // Assume we cannot continue after this exception so we'll return or 
     // rethrow to exit the method 
     return; 
    } 
} 

这里,我们使异常处理逻辑一起和变量的范围内声明他们正在使用。但是对我来说,异常处理逻辑似乎不太清晰,因为它远离了原点。 有没有人有意见哪一个会更好,或者我只是担心毫无意义的细节,应该继续工作? :-)

感谢

+0

异常处理是花费时间的。 –

+0

@SuzanCioc在规划和编码方面还是在执行方面?你在两个方面都是正确的,但我肯定会认同异常处理需要很多思考,有时甚至超过实际的正常业务逻辑流程。 – dassimon

回答

0

我宁愿既取决于条件。

案例1

Object obj; 
    try { 
    // do something 
    } catch (Exception e) { 
     obj = default_obj; // assign default object 
    } 

    try { 
     // do something either with specific or default object 
    } catch (Exception e) { 
     // handle exception 
    } 

这里,即使第一次尝试捕获失败,继续默认值

案例2

try { 
    Object obj; 
    // acquire object 

    // do something only if acquire object is successful 
} catch (Exception e) { 
    // handle exception 
} 

这里不继续进行动作当获取对象不成功时。

这里是处理异常的方式比风格更需要的。

1

我相信在所有的情况下,答案都不是从技术分析中明显产生的,应该忽略最初的开发工作并研究代码的未来。

为此,我建议第一种方法是最好的选择,除非有真正的技术理由选择第二种方法。

总结:

如果有两种风格之间没有技术差异,考虑你的代码的未来读者,使其尽可能明显。

+1

同意,我的大部分时间都花在使用不同质量的遗留代码上,有些可能是一个真正的尝试去理解的痛苦。随着代码的老化,清晰度变得比没有文档,难以理解的优雅和聪明更重要。我认为@Marko确实在这种情况下增加了技术差异。 – dassimon

1

异常之美是你不必处理它们发生的地方。这就是为什么你其实应该用你的第二个样式,但没有外的try-catch

public void useMethodNestedHandlers() { 
    Object o1 = exceptionMethod(); // Can be declared inside scope where it is used 
    // Do something that requires o1 
    for (int i = 0; i < 100; i++) { 
     try { 
      Object o2 = exceptionMethod(); // Can be declared inside scope where it is used 
      // Here we would use the objects in some manner 
      boolean equal = o1.equals(o2); // Just a pointless example 
              // to show that both objects 
              // are required 
      // Assume the method does a load of stuff down here 
     } catch (Exception ex) { 
      // Assume we can continue to the next iteration after this 
      // exception 
      continue; 
     } 
    } 
} 

代码为快乐天的情况下,让有关故障别人担心。这是实现问题分离的方式:通常所有失败都由同一段代码处理,并且过早捕获会产生重复的代码。

+0

感谢您的回复,我认为我同意您在异常情况下不能在源代码中显式处理异常时将异常进一步抛出调用堆栈,并在某些常见异常处理位置处理它们。虽然我不认为只是懒惰地重新抛出任何以我的方式出现的东西(尽管这比在空的catch块中吞食异常仍然更好)。至于让其他人担心失败,通常最终会成为我的无论如何:-) – dassimon

+0

是的,我只是用人格化的风格来谈论代码。当然,你,作家,谁控制双方傀儡:)你为什么认为它是懒惰的让异常传播?失败就是失败。它的具体细节与程序无关,仅限于开发者,并且由异常堆栈追踪完美服务。 –

+0

我猜我认为这是懒惰的,因为一些异常可以在源头处理,所以应该考虑是否需要重新抛出。不过,我认为开发人员(或团队)仍然有责任确保异常处理的位置在不低于懒惰的调用堆栈的某个位置。 – dassimon

0

该代码应该是1)正确的,2)可读的。通常所有不可恢复的异常都应该在最高层的应用程序中处理(或根本不应该)。这意味着它们应该正确显示给用户。所有可恢复的例外应该尽可能地处理“尽可能高”。我建议使用尽可能少的try-catch语句

相关问题