考虑以下代码:
x = Repo.GetX(13);
Services.Process(x);
我可以在处理它之前检查x是否为null,或者如果X为null并使用try / catch块,我可以让Services.Process()抛出异常。
哪种方法更可取?
(或者我应该同时做两件事,只是在特殊情况下x从检索到处理它的某种程度上变为空?)
答案 0 :(得分:1)
像往常一样,这类问题的正确答案是:它取决于。
如果可能,最好的方法是定义执行此类检查的边界。边界内的所有东西都可以依赖于所有被初始化的东西。如果仍然是一个NULL偷偷摸摸,用NPE炸毁是非常合适的。
通常在尝试执行实际工作之前检查前提条件可以使代码更清晰。
如果你不能在你的系统中建立这些边界,那么问题是:当x为NULL并且未处理结果异常时会发生什么,当你不处理它时你有什么选择?
在许多情况下,无论如何你都无法做很多事情,然后让异常上升到ui(或服务接口或其他)的调用堆栈就好了。
但有时使用null参数调用进程会破坏硬件,杀死病人或者其他方面真的很讨厌。在这种情况下:在潜在的有害行为之前检查。
答案 1 :(得分:1)
如果你想在以下两者之间作出决定:
x = Repo.GetX(13);
try {
Services.Process(x);
} catch (NullPointerException) {
System.err.println('x is NULL');
}
或
x = Repo.GetX(13);
if (x != NULL) {
Services.Process(x);
} else {
System.err.println('x is NULL');
}
然后要注意他们并不意味着同样的事情。第一个捕获由Process
抛出的任何 NullPointerException。第二个只处理x
本身为NULL的情况 - 如果Process
执行x.foo().bar()
,x.foo()
返回NULL,则不处理。
您应根据可以处理的错误来决定两者之间的关系。
在Services.Process
被记录为抛出NullPointerException的情况下,当且仅当x
为NULL时,所以(假设我们相信文档)两者的意思相同,那么我就是做第二个。这样,如果文档是谎言,并且Services.Process
中有一个错误导致它抛出其他情况,那么我们就不会错误地处理/报告异常,就好像x
实际上是NULL一样它不是。
因此,在两种情况下捕获并抑制异常:
不要因为你知道可能导致异常的一个情况而抓住,并且当出于其他原因可能抛出相同的异常时可以处理。我想你可以做到:
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');
}
我们可以在调用s
之前检查parseFloat
是否是有效数字,但这基本上会做同样的工作两次 - 检查一个字符串是一个有效的浮点数是与实际转换它几乎一样。所以抓住这个例外是有意义的 - 我们知道这意味着什么,我们知道如何应对它,我们无法真实地阻止它发生。
(或者你可以使用DecimalFormat.parse,它根本不会抛出)
答案 2 :(得分:0)
更好的检查。异常处理通常很昂贵。
答案 3 :(得分:0)
应该使用异常处理来处理异常。
如果你的东西 x 永远不应该为null,请使用try / catch语句。如果 x 在某些情况下将为null use和if。