9

考虑以下 Cocoa/Obj-C 代码片段:

MyClass *obj;
@try {
    [obj doSomething];
}
@catch (NSException * e) {
    NSLog(@"Exception occurred: %@", [e description]);
}
@finally {
    [obj cleanUp];
}

MyClass *obj;
@try {
    [obj doSomething];
}
@catch (NSException * e) {
    NSLog(@"Exception occurred: %@", [e description]);
}
[obj cleanUp];

在什么情况下第一个片段会被[obj cleanUp]调用,而第二个片段不会[obj cleanUp]被调用?换句话说,在什么情况下@finally使用 Cocoa 异常处理是非冗余的?

4

5 回答 5

15

在这些情况下没有区别,因为异常被吞没了。这里有两个不同的场景:

[obj cleanUp] 被称为:

MyClass *obj;
@try {
    [obj doSomething];
}
@catch (NSException * e) {
    @throw;      
}
@finally {
    [obj cleanUp]; // called when exception is caught
}

[obj cleanUp] 未被调用:

MyClass *obj;
@try {
    [obj doSomething];
}
@catch (NSException * e) {
    @throw;
}
[obj cleanUp]; // not called when exception is caught
于 2009-04-12T13:44:07.920 回答
7

还值得注意的是,当控制出于任何原因@finally退出@try块时,块中的代码将运行,即使是通过或。例如:returngoto

@try {
    doStuff();
    if(bail){
        return;
    }
    doMoreStuff();
}
@finally {
    [obj cleanUp];
}
[obj announceSuccess];

[obj cleanUp]即使bail是真的也会执行,但[obj announceSuccess]不会。

于 2010-11-10T20:53:34.747 回答
5

在那种情况下,你正在压制异常,没有。@finally用于在您未捕获异常或重新抛出异常时进行清理,在任何一种情况下都会将最终异常响应留给调用代码。由于 Cocoa 中的异常只应该用于编程错误,因此很少发生,这是完全合理的做法。

还值得指出一种不需要使用的情况@finally,即设置自己的自动释放池时。当“父”自动释放池被销毁时,任何尚未清理的内部自动释放池也将被销毁。如果您确实尝试自己清理它,则需要将异常本身从您的自动释放池中提升出来。

于 2009-04-12T11:01:44.003 回答
1

什么时候:

  • 您没有捕捉到发生的异常类型
  • 您捕获了异常,但 catch 块中的代码也会引发异常。
于 2009-04-12T11:05:41.327 回答
0

一个较低级别的问题,你为什么要这样做?

try/catch/finally 方法在 Java 中被广泛使用,但在 Objective-C 中几乎没有使用过,并且不是首选方法 - 你根本不需要它,因为库不会像 Java 库调用那样抛出异常,如果你正在编写自己的库,您不应该期望调用者自然会想到寻找要捕获的异常。

最广泛使用和理解的约定是具有错误方法回调的委托,或者可能通知您需要通过多个代码级别传递的更一般的故障。如果有一个像 Cocoa 那样设置的简单通知系统,那么这种方法可能会在 Java 世界中得到更广泛的应用。

委托方法与在 Java 中声明异常具有相同的文档属性,它们只是不同的方法,但通常最好使用更适合手头语言的方法,除非有非常令人信服的理由不这样做。

于 2009-04-13T06:26:25.013 回答