この関数はFileNotFoundExceptionを介して実行できますが、これを呼び出してから、trycatchに基づいて何かを実行するのは悪い習慣です。
同意しません。IMO、開く前にファイルが存在するかどうかをテストしていますが、これは悪い習慣です。次の2つのバージョンのコードを比較します。
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には競合状態があります。ある外部プロセスがほぼ同時にファイルを削除すると、file.exists()
trueが返され、FileInputStream
コンストラクターが。をスローする可能性がありますFileNotFoundException
。これは、問題のファイルがセキュリティ上重要である場合にセキュリティを破るために悪用される可能性のある競合状態の一種です。
(実際には、2番目の競合状態もあります。file.exists()
ファイルの作成中に呼び出すと、ファイルが返さfalse
れる場合があります。その場合、成功した可能性がありますが、エラーメッセージが出力されますnew FileInputStream
。この競合状態はおそらく無害です。)
さらなる問題は、FileInputStream
がthrowingとして宣言されていることIOException
です。ファイルが存在するかどうかを確認するためのテストでは、考えられる障害モードの1つのみを処理します。あなたのコードはIOException
とにかく他のものを処理する必要があります。
@Piecesのコメント:
例外は、あなたが制御できない何かが実際にうまくいかない場合のためです。この場合、私はそれを完全に制御できます。
実際、あなたはそれを完全に制御することはできません。確かに一般的なケースではありません。特定のユースケースでも、理論的には競合状態が発生する可能性があります。
しかし、この考え方の本当の問題は、例外/例外処理が最善の解決策である状況で、例外を回避するためにフープを飛び越えてしまうことです。これにより、コードがより複雑になり、読みにくくなり、速度が低下したり、壊れやすくなる可能性があります。
通常の教義は次のようになります。
「例外は、例外的な状況でのみ使用する必要があります」。
これはあなたが言ったことを言うことと同じではありません。「例外的」という言葉は、実際には「正常ではない」という意味です。これは、「あなたが制御できない何かが実際にうまくいかない」よりもはるかに広い意味を持っています。
私は次のように教義を拡張する傾向があります:
通常のフロー制御には例外を使用しないでください。
例外は、平均して高すぎることが判明する場合は使用しないでください。
例外を回避するために使用するテストが信頼できない場合は、例外を使用する必要があります。
例外を回避するために使用するテストが平均して高すぎる場合は、例外を使用する必要があります。
コードを大幅に単純化する場合は、例外を使用する必要があります(上記を法として)。そして、単純さの基準は、コードが平均的なJavaプログラマーによって読み取れるかどうかです。
(注-「平均して」および「高すぎる」...)
これで、牛が家に帰るまで、イベントがどれほど例外的である必要があるかについて議論することができますが、これは実際には、アプローチの相対的な単純さ(コンテキストで)と平均パフォーマンスコスト(コンテキストで)のバランスの問題であるということです)。トレードオフとコンテキストを考慮しない独断的なルールは、場合によっては害を及ぼします。