该函数可以通过FileNotFoundException,但我觉得调用它然后根据尝试捕获做一些事情是不明智的做法。
我不同意。IMO,它是在打开之前测试文件是否存在,这是不好的做法。比较以下两个版本的代码:
File f = new File("someFile");
InputStream is;
版本 #1
if (f.exists()) {
is = new FileInputStream(f);
...
} else {
System.err.println("Doesn't exist");
}
版本 #2
try {
is = new FileInputStream(f);
...
} catch (FileNotFoundException ex) {
System.err.println("Doesn't exist");
}
第一个版本存在许多问题:
版本 #1 会在您调用 时进行额外的系统调用。这使得第一个版本平均速度较慢,除非该文件很有可能不存在。f.exists()
-
版本 #1 具有争用条件。如果某些外部进程在大致相同的时间删除文件,则最终可能会返回 true,然后构造函数引发 。如果相关文件对安全性至关重要,则可以利用这种争用条件来破坏安全性。file.exists()
FileInputStream
FileNotFoundException
(实际上,还有第二个竞争条件。如果在创建文件时调用,它可能会返回 。在这种情况下,您将打印错误消息,即使可能成功。此争用条件可能是无害的。file.exists()
false
new FileInputStream
另一个问题是 被声明为 throwing 。测试以查看文件是否存在仅处理一种可能的故障模式。无论如何,您的代码将不得不处理其他s。FileInputStream
IOException
IOException
@Pieces评论道:
例外情况应该是当某些事情实际上出了问题,而您无法控制。在这种情况下,我可以完全控制它。
实际上,您无法完全控制它。当然不是在一般情况下。即使在您的特定用例中,竞争条件在理论上仍然是可能的。
但是这种思维方式的真正问题是,在异常/异常处理是最佳解决方案的情况下,您最终会跳过箍以避免异常。这使得代码更复杂,可读性更差,并且可能更慢和/或更脆弱。
正常的教条是这样的:
“例外情况只应在特殊情况下使用”。
这与说你说的话是不一样的。“例外”这个词实际上只是意味着“不正常”。这比“你无法控制的事情实际上出了问题”的含义要广泛得多。
我倾向于将教条扩展如下:
不应将异常用于正常流量控制。
如果平均而言,异常将被证明过于昂贵,则不应使用它们。
如果用于避免异常的测试不可靠,则应使用异常。
如果您用于避免异常的测试平均成本太高,则应使用异常。
如果异常显著简化了代码(上面的模数),则应使用它们。简单性的标准是代码是否被普通的Java程序员读取。
(注意 - “平均”和“太贵”...)
现在,人们可以争论,直到奶牛们回家,一个事件需要多么特别,但我的看法是,这实际上是一个平衡方法的相对简单性(在上下文中)与平均性能成本(在上下文中)的问题。任何不考虑权衡和上下文的教条规则在某些情况下都会对你造成伤害。