Language agnostic 在流程之前进行验证更好,还是只抛出异常更好?
考虑以下代码:Language agnostic 在流程之前进行验证更好,还是只抛出异常更好?,language-agnostic,error-handling,Language Agnostic,Error Handling,考虑以下代码: x = Repo.GetX(13); Services.Process(x); 我可以在处理它之前检查x是否为null,或者我可以使用Services.Process()在x为null时抛出异常并使用try/catch块 哪种方法更可取 (或者我应该两者都做,只是在例外情况下,x从检索到处理它都以某种方式变为空?检查要好得多。异常处理通常很昂贵。像往常一样,这类问题的正确答案是:视情况而定 如果可能,最好的方法是定义执行此类检查的边界。边界内的所有内容都可以依赖于所有内容的良好
x = Repo.GetX(13);
Services.Process(x);
我可以在处理它之前检查x是否为null,或者我可以使用Services.Process()在x为null时抛出异常并使用try/catch块
哪种方法更可取
(或者我应该两者都做,只是在例外情况下,x从检索到处理它都以某种方式变为空?检查要好得多。异常处理通常很昂贵。像往常一样,这类问题的正确答案是:视情况而定 如果可能,最好的方法是定义执行此类检查的边界。边界内的所有内容都可以依赖于所有内容的良好初始化。如果仍然有空的潜入,用NPE引爆是非常合适的 通常,在尝试执行实际工作之前检查先决条件会使代码更加清晰 如果您无法在系统中建立这些边界,那么问题是:当x为NULL且结果异常未被处理时会发生什么,当您不处理它时,您有什么选择 在许多情况下,您无论如何也不能对此做太多,然后让异常从调用堆栈上升到ui(或服务接口或其他任何东西)也没关系
但有时使用空参数调用进程会破坏硬件,杀死患者,或者真的很糟糕。在这种情况下:在潜在的有害操作之前进行检查。应使用异常处理来处理异常
如果您认为x不应该为null,请使用try/catch语句。Ifx在某些情况下将为空,请使用和If语句。如果您试图在以下两者之间做出选择:
x = Repo.GetX(13);
try {
Services.Process(x);
} catch (NullPointerException) {
System.err.println('x is NULL');
}
或
然后要意识到它们的意思并不相同。第一个捕获由进程
引发的任何NullPointerException。第二个仅处理x
本身为NULL的情况-如果Process
执行x.foo().bar()
,并且x.foo()
返回NULL,则不处理该情况
你应该根据你能处理的错误在两者之间做出选择
在Services.Process
被记录为抛出NullPointerException的情况下,当且仅当x
为NULL时,因此(假设我们相信该文档)这两者的含义相同,那么我将执行第二个。这样,如果文档是假的,并且Services.Process
中有一个bug导致它在其他情况下抛出,那么我们就不会错误地处理/报告异常,就好像x
是空的,而实际上它不是空的
因此,在两种情况下捕获并抑制异常:
x = Repo.GetX(13);
try {
Services.Process(x);
} catch (NullPointerException) {
if (x == NULL) {
System.err.println('x is NULL');
} else {
throw;
}
}
但在这种情况下,这似乎是不必要的冗长:因为我们可以提前检查x
是否为空,所以我们也可以这样做。但是,在某些情况下,您捕获异常是因为不可能或只是愚蠢地试图提前预测它是否会发生:
String s = Rep.GetString(13);
try {
f = Float.parseFloat(s);
System.out.println('is a number');
} catch (NumberFormatException) {
System.out.println('not a number');
}
在调用parseFloat
之前,我们可以检查s
是否是一个有效的数字,但这基本上需要做两次相同的工作-检查字符串是否是有效的float与实际转换它几乎是一样的。所以抓住这个例外是有意义的——我们知道它意味着什么,我们知道该怎么做,我们不可能现实地阻止它发生
(或者您可以使用DecimalFormat.parse,它根本不会抛出任何错误)只要这段代码不是在一个巨大的循环中运行,就不应该考虑性能。如果它确实在紧循环中运行,那么应该进行性能测试,并基于这些测试来调整实现。当“异常”情况很常见时,异常处理通常是昂贵的。如果一千次中只有一次发生,实际上跳过检查并抛出异常会更快。正如另一个答案所说,这要视情况而定。除了性能,这里还有其他需要担心的事情。
String s = Rep.GetString(13);
try {
f = Float.parseFloat(s);
System.out.println('is a number');
} catch (NumberFormatException) {
System.out.println('not a number');
}