4

Java には特定の事前定義された例外があり、スローされた場合、重大な問題が発生したことを報告し、catch ブロックでそれらをキャッチするよりもコードを改善する必要があります (私が正しく理解している場合)。それでも、次のようなプログラムがたくさんあります。

} catch (IOException e) {
     ...
} catch (FileNotFoundException e) {
     ....
}

IOException と FileNotFoundException はまさにそのような種類の例外であり、catch ブロックでキャッチすべきではないと思いました。なぜ人々はこれを行うのですか?このまま捕まえたほうがいいの?とにかく、Java コンパイラーはその種の問題について警告します。

ありがとうございました。

4

7 に答える 7

3

Jon が言うように、多くの場合、これらの例外をキャッチすることは問題ありません。キャッチしてはならない種類の例外は、NullPointerException や ArrayIndexOutOfBoundsException などで、これらはコードのバグを示しています。

Java には、チェック済み例外とチェックされていない例外 (RuntimeException から継承されたもの) の 2 種類の例外があります。

IOException などのチェック済み例外は、通常、より適切なコードを記述しても回避できない予測不可能なシナリオに使用されます。それらがチェックされるという事実は、例外的なシナリオの可能性を説明するコードを書くことをコンパイラーが強制することを意味します。たとえば、ファイルが存在することを保証できないため、FileNotFoundException の可能性を考慮する必要があります (プログラムの実行中に誰かがファイルを移動する可能性があります)。ネットワーク接続が切断されたために、IOException が発生する場合があります。コンパイラは、これらのケースに対処するための戦略を提供することをユーザーに強制します。たとえそれが、処理するコードを呼び出すために例外をスタックに伝播させることによって責任を転嫁するだけであってもです。

一方、チェックされていない例外は、コードを変更することで回避できるものに最適です。コードが null 参照の可能性をチェックする場合、NullPointerException は常に回避できます。同様に、インデックスに注意すれば、ArrayIndexOutOfBoundsException が発生することはありません。これらのシナリオは修正が必要なバグであるため、コンパイラはこれらのシナリオを処理する義務はありません。

于 2009-02-10T23:51:15.640 に答える
3

IOException と FileNotFoundException はまさにそのような例外だと思いました

いいえ、それらは実際には「その他の」タイプの例外であり、プログラミングスキルを超えた種類のものです。どんなに優れたプログラムを作成しても、コンパイラとライブラリを使用すると、何かが起こる可能性があることを「意識」できます。

次のシナリオについて考えてみてください。

データを一時フォルダーに保存するアプリケーションを作成します。

すべて問題ありません。フォルダーが存在することを確認しました。存在しない場合は、自分で作成します。

そして、その一時フォルダーに 2 MB を書き込みます。

突然、他のシステム プロセスによって一時フォルダーが削除され、書き込みができなくなります。

これをプログラムで防ぐためにできることは何もありません.一部のシステムでは、その操作が発生する可能性があります. let other process delete a file is used )

コード内のこの種の例外をチェックするように強制することで、プラットフォームの設計者は、少なくともこれを認識していると考えました.

ジョンは正しいです。おそらく、プログラムが終了する前にログを記録することは、「例外を処理する」と見なされます(処理が不十分ですが、少なくとも処理します)

try { 
   .... 
} catch( IOException ioe ) { 
    logger.severe( 
        String.format("Got ioe while writting file %s. Data was acquired using id = %d, the message is: %s", 
             fileName, 
             idWhereDataCame,
             ioe.getMessage()) );
  throw ioe;
}

他にできることは、抽象化に合わせて例外を「チェーン」することです。

おそらくあなたのアプリケーションには GUI があり、ユーザーに IOException を表示しても何の意味もないか、セキュリティの脆弱性である可能性があります。変更されたメッセージが送信される可能性があります。

try { 
   .... 
} catch( IOException ioe ) { 
   throw new EndUserException("The operation you've requeste could not be completed, please contact your administrator" , ioe );
}    

また、EndUserException は GUI のどこかにトラップされ、ダイアログ メッセージでユーザーに提示される可能性があります (詳細な情報なしでアプリが目に見えなくなるのではなく)。もちろん、その IOException を回復するためにできることは何もありませんでしたが、少なくともスタイルで死ぬ :P

最後に、クライアント コードはさまざまな実装を使用でき、すべての例外が意味を成すわけではありません。

たとえば、最初のシナリオをもう一度考えてみてください。その同じ「操作」には、データの保存を実行するための 3 種類の「プラグイン」サービスが含まれる場合があります。

a) Write the data  to a file.
b) Or, write to a db
c) Or write to a remote server. 

インターフェースは以下をスローすべきではありません:

java.io.IOException
java.sql.SQLException 

または

java.net.UnknownHostException

しかし、代わりに次のようなもの

my.application.DataNotSavedException

そして、さまざまな実装が正しいレベルで例外を処理し、適切な抽象化に変換します

クライアントコード:

 DataSaver saver = DataServer.getSaverFor("someKeyIdString");

 try {
     saver.save( myData );
 } catch( DataNotSavedException dnse ) {

     // Oh well... .
     ShowEndUserError("Data could not be saved due to : " dnse.getMessage() );
 }

実装コード:

 class ServerSaver implements DataSaver { 
 ....
     public void save( Data data ) throws DataNotSavedException {
         // Connect the remore server.
         try { 
             Socket socket = new Socket( this.remoteServer, this.remotePort );
             OuputStream out = socket.getOut.... 

             ....
             ....
         } catch ( UnknownHostException uhe ) { 
            // Oops....
            throw new DataNotSavedException( uhe );
         }
    }
 }

FileSaver と DatabaseSaver は同様のことを行います。

これらはすべて、コンパイラによってチェックされるため、チェックされた例外です。

どちらか一方を使用する場合 (オン/オフ):こちら

他に2種類あります:こちら

最後に、ランタイムのより簡単な説明は次のとおりです。

于 2009-02-11T00:29:45.173 に答える