示例#1:
try { fileChooser.setSelectedFile(new File(filename)); }
catch (NullPointerException e) { /* do nothing */ }
示例#2:
if (filename != null)
fileChooser.setSelectedFile(new File(filename));
由于性能或稳定性(或任何其他原因),#1本质上是不好的,还是只是有点不同?这不是一个很好的例子,因为#1优于#2没有优势,但在不同情况下可能会有(例如提高可读性,减少代码行数等)。
编辑:协商一致似乎是#1是禁忌。最受欢迎的原因:开销
此外, @Raph Levien 有很好的见解:
避免#1的一个原因是它会使您使用异常断点的能力中毒。正常运行的代码永远不会故意触发空指针异常。因此,将调试器设置为每次发生时都停止是有意义的。在#1的情况下,您可能会例行地获得此类异常。除了其他充分的理由之外,还有潜在的性能影响。
此外,See Link更深入。
答案 0 :(得分:8)
绝对是#2是更好的选择。不应将异常处理用作程序控制流中的构造。应该使用例外来处理不受程序员控制的情况。在此示例中,您可以检查fileChooser是否为null,以便您可以控制。
答案 1 :(得分:5)
异常会带来一定的开销。如果可以避免它们,在这种情况下,只需检查一个null,那将是首选。
正如其他人所说,使用Exceptions进行流量控制通常也是不好的做法。有关错误原因的详细说明,请查看this.
以下是答案的简短说明:
异常基本上是非本地goto语句,具有后者的所有后果。使用流控制的异常违反了最不惊讶的原则,使程序难以阅读(记住程序首先是为程序员编写的)。
答案 2 :(得分:5)
fileChooser==null
还是fileName==null
。答案 3 :(得分:4)
如果程序在逻辑上允许空值,请对其进行测试。否则使用例外。例外是为了处理异常情况(惊喜!),不应该用于程序逻辑。
答案 4 :(得分:3)
避免#1的一个原因是它会使您使用异常断点的能力中毒。正常运行的代码永远不会故意触发空指针异常。因此,将调试器设置为每次发生时都停止是有意义的。在#1的情况下,您可能会例行地获得此类异常。除了其他充分的理由之外,还有潜在的性能影响。
答案 5 :(得分:2)
我选择#3选项 - 如果filename
作为函数参数传递,请在注释中注明不允许使用空文件名。然后只需假设文件名永远不为空:
fileChooser.setSelectedFile(new File(filename));
如果某个白痴(或你,< 3)忽略了你的评论并且''确实''传递了一个null,他将得到一个NullPointerException并且必须解决问题。
在客户端代码中,始终通过初始化或将fileName
默认为空字符串来确保没有传递空值。
我一直在避免使用和接受空值一段时间,而且我的代码更清晰,因为它已经没有那么多的空检查了。唯一仍然存在的空检查是我调用可能返回null的第三方代码的那些。
(咆哮:当然,我必须反编译所说的第三方代码并确定我自己,考虑到文档不存在或者没有记录它可能返回null)
答案 6 :(得分:2)
在以下情况下,您的两个示例在语义上不相同:
fileChooser
是null
setSelectedFile
抛出一个NullPointerException
(授予,这种特殊方法不会发生这种情况,但一般情况下,setter很可能将东西存储在其他对象中,如果该另一个对象的引用未初始化)new File()
因“NullPointerException
filename
null
可能/* do nothing */
仅适用于filename
为空的情况,但现在也隐藏其他情况,而良好的异常处理会允许这些异常冒泡调用堆栈,警告你要找到一个你很难找到的错误的存在和原因。
我觉得这比性能更令人信服,因为浪费的程序员时间比浪费的cpu时间贵得多。