0

我试图了解异常条件的来源。我的问题在最后,但我将举一个可能更清楚的例子。


以这个 Java 代码为例。它具有文件的路径并设置了一个File对象。如果路径为空,则抛出异常。

String path = getPathName();
try {
    File file = new File(path);
} catch (NullPointerException e) {
    // ...
}

不过,这几乎不是一个例外情况,如果我们可以修改它以使其更可取:

String path = getPathName();
if (path == null) {
    path = DEFAULT_PATH;
}
File file = new File(path); # we've removed the need for an exception

但更进一步,当我们尝试使File可读性更好时,我们遇到了一个新的异常。

try {
    file.setReadable(true);
} catch (SecurityException e) {
    // ...
}

我们可以通过检查两个条件来绕过这个问题:

SecurityManager sm = System.getSecurityManager();
if (sm != null && sm.checkWrite(path)) {
    // modify the SecurityManager
} else {
    file.setReadable(true);
}

考虑到这个例子,关于我的问题......


如果我们向下移动堆栈,从 Java 到 OS 等,是否可以用 if-else 分支替换所有异常处理代码?或者是否有一些异常(硬件?)的根本原因意味着它们被“烘焙”到编程中?

4

2 回答 2

4

如果我们向下移动堆栈,从 Java 到 OS 等,是否可以用 if-else 分支替换所有异常处理代码?

是的。这就是它过去的做法,并且仍然毫无例外地使用语言。使用例外是因为它们在许多方面更容易。主要优点是程序员没有预料到的情况可以在通用处理程序中聚合;并且在正确处理之前,不需要在每个函数中明确保留有关异常情况的信息。

或者是否有一些异常(硬件?)的根本原因意味着它们被“烘焙”到编程中?

也是的。通常,需要以某种方式处理意外的硬件条件,除非您对这种情况下的未定义行为感到满意。

于 2013-07-26T16:29:48.847 回答
0

如果程序中的所有方法都返回一个指向某种“异常”对象的指针/引用(对于其他返回值,传递一个指针或对调用者分配的存储位置的引用),并且如果对每个方法的每次调用都可能直接或间接想要抛出异常的括号括起来:

ret = callFunction( ...parameters...);
if (ret != NULL)
  return AddToExceptionStacktrace(ret, ...info about this call site... );

那么就不需要任何其他形式的异常处理(请注意,如果类型支持作用域变量,则“return”语句必须插入代码以在实际返回给调用者之前清理它们)。

不幸的是,这是很多额外的代码。这种方法在只有“已检查”异常的语言中是可行的(这意味着一个方法既不能抛出异常也不能通过它们,除非它被声明为这样做),但是将这种开销添加到每个可能直接或间接调用的函数抛出异常的函数将非常昂贵。异常处理机制通常消除了无异常情况下 99% 的额外开销,以及在“异常”情况下增加开销的开销。

于 2013-07-26T19:35:58.860 回答