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;
    }
}

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

谢谢

4

4 回答 4

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;
        }
    }
}

为快乐的一天编写代码,让其他人担心失败。这就是实现关注点分离的方法:通常所有故障都由同一段代码处理,并且过早捕获重复代码。

于 2012-10-11T12:15:44.667 回答
1

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

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

总之:

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

于 2012-10-11T12:12:14.037 回答
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
}

获取对象不成功时,此处不再继续。

在这里,处理异常的方式与其说是一种风格,不如说是一种必要性。

于 2012-10-11T12:04:20.903 回答
0

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

于 2012-10-20T23:22:56.607 回答