你喜欢在哪里捕捉异常,为什么?
我很想看看人们觉得在哪里放置他们的 try/catch 块很有用,希望可能出现一些通用模式。我将用 C++ 发布我的两个示例答案,但任何语言都可以。
请为每个答案提供一个位置和原因。谢谢。
你喜欢在哪里捕捉异常,为什么?
我很想看看人们觉得在哪里放置他们的 try/catch 块很有用,希望可能出现一些通用模式。我将用 C++ 发布我的两个示例答案,但任何语言都可以。
请为每个答案提供一个位置和原因。谢谢。
不要抓住任何你没有准备好也没有能力处理的东西。
因此,拥有顶级异常处理,以您喜欢的方式对意外异常进行轰炸,然后只捕获您需要的东西(尽可能接近它可能发生的地方)以获得所需的功能。
你应该只做两件事之一:实际做一些事情来解决/解决问题,或者重新抛出一个更具描述性的异常,将捕获的异常作为其innerException
.
编辑:如果您需要一个finally
块(例如,释放您在代码中分配的内容)并且您对可能弹出相同逻辑的任何异常没有任何用处:只需不处理它们。相反,使用 acatch { throw; }
将异常重新抛出到更高级别,同时保持所有异常信息不变。(或者干脆省略 catch 块,我认为/希望做同样的事情?)
我试图只捕获那些我可以处理的异常。
我讨厌这样的代码:
String s="12";
Integer i;
try {
i = Integer.parseInt(s);
} catch(ParseException pe) {
System.out.println("hihihihihihihi!!!);
}
我特别讨厌的是,这通常是无论如何都会中止线程,因为三行之后将访问 i 并假设 i != null。
然后,您将阅读您的堆栈跟踪并滚动并滚动并滚动日志,直到您找到第一个使其他所有内容崩溃的重大错误。
无论如何,我希望 Java 不会强迫我捕获我无法处理的异常。但我能做的是:
catch(Exception e) {
throw new RuntimeException(e);
}
我在函数定义中声明了很多“抛出”。
我仍然梦想着有一天 Eclipse 会在遇到未捕获的异常时自动在正确的行中打开一个调试器。那天,我的方法将打开正确的行。
在其他语言中,比如 Smalltalk,我只捕获我可以处理的错误。当输入不符合我的期望时,我很乐意抛出未捕获的异常。
这个想法是我不希望记录或记录错误。我想把它修好。
我总是在 main() 中添加一个捕获作为最后的捕获:
int main( int argc, char** argv ) {
try {
Application application( argc, argv );
return application.result();
}
catch ( const std::exception& exception ) {
fprintf( stderr, "%s.\n", exception.what() );
}
}
在 C# 和 Java 中,我更喜欢根本不捕获异常。如果无法避免,我会立即重新抛出运行时异常。
我将始终使用所需范围最大的最贪婪的 catch 块,但始终使用最具体的异常类型。由于在 99.99% 的情况下,catch 块的结果是另一个 throw,因此我尝试将完整方法保留在 try 块中。
我喜欢尝试将我的异常处理代码与其他代码分开,因此我通常创建一个辅助方法来执行实际逻辑,而外部方法只处理异常处理。我一直认为这使代码看起来更干净,并且更具可读性。
public void stuff() throws MyException
{
try
{
tryStuff();
}
catch (SomeLibraryException e)
{
logger.log("Some message happened", e);
throw new MyException(e);
}
}
public void tryStuff() throws SomeLibraryException
{
// Do things in here that could throw exceptions
}
(在我开始之前:我是一个 Java 人)
我的建议是:
handle(Exception e)
方法的异常处理程序类,并最初将其发布给团队,并确保每个人都使用它来处理异常。根据不断变化的异常处理场景,稍后继续添加重载的“处理”方法,以便只修改处理程序。我喜欢在控制器中处理处理从视图触发的事件的处理程序。如果异常提供了强有力的安全保证,这是一个有用的捕获点,因为它的级别足够高,可以报告错误,并且处理程序通常是原子的并且与用户刚刚完成的事情相关,因此希望他们能够解决这是怎么回事。
void Controller::on_edit_entity( const Entity& entity ) {
try {
Command::ptr command = new EditEntityCommand( entity );
push_command( command );
}
catch ( const std::exception& exception ) {
fprintf( stderr, "%s.\n", exception.what() );
}
}
在Delphi Windows 应用程序中,应用程序的主消息处理循环(即在调用堆栈的底部)通过显示一个消息框来处理您的异常。在我看来,这是处理异常的最佳场所。
通过在您自己的方法中捕获异常以向用户显示消息框的唯一目的,您拒绝任何调用您的方法的代码知道异常实际发生并且该方法实际上失败了。
我只会在以下情况下处理异常:
两个地方: