3

さて、質問のタイトルはそれをすべて言います。

コードを提示する前に、いくつかのポイントがあります。

  • 特定の種類の例外が特定のステートメントのセットで発生することがわかっている場合、それらすべてを1回の試行で、対応するcatchをすぐに配置することをお勧めしますか?
  • または、例外が発生しやすいすべてのコードを1つのコードブロックに配置し、その1回の試行後に対応するすべてのcatchブロックを配置する必要があります。それに関連するパフォーマンスコストはありますか?

    {   
        try
        {
             exec();//can cause ExceptionXYZ
        }
        catch(ExceptionXYZ e){ }            
        try
        {
             exec(); //can cause ExceptionPQR
        }
        catch(ExceptionPQR e){ }
            try
        {
             exec(); //can cause ExceptionABC
        }
        catch(ExceptionABC e){ }
    }
    

それで、上記の方法は良いですか、それとも1つ以下ですか

    {
        try
        {
             exec(); //can cause ExceptionXYZ          
             exec(); // can cause ExceptionPQR        
             exec(); //can cause ExceptionABC
        }
        catch(ExceptionXYZ e){ }
        catch(ExceptionPQR e){ }
        catch(ExceptionABC e){ }
    }

また、 try in tryのネストのように、上記の2つのパターンが混在する可能性もあります。 いつ使用するかについての他の考慮事項/ポイントはありますか?1つは、ネストによってコードが少し複雑になることです。

データベースを閉じるときのような他のシナリオでは、他にもいくつかの考慮事項があります-JDBCリソースでは、1つのclose()でNullPointerExceptionが他のリソースを開いたままにしないようにするために、すべてのクローズを個別に処理する必要があります。

    try
    { } 
    catch(Exception e)
    { }
    finally
    {
        if (rs != null)  //ResultSet
            try 
            {
                rs.close();
            }
            catch(SQLException se1)
            {
                se1.printStackTrace();
            }
        if(pstmt!=null)  //PreparedStatement
            try
            {
                pstmt.close();
            }
            catch(SQLException se2)
            {
                se2.printStackTrace();
            }
        if(conn!=null)   //Connection
            try
            {
                conn.close();
            }
            catch (SQLException se3) 
            {
                se3.printStackTrace();
            }   
    }

何かご意見は?または、不必要に考えすぎています。

編集

いくつかの考慮事項/事実(考えすぎ:p)

  • 一般化するだけです。いずれにせよ実行する必要のあるコードブロックがいくつかある場合は、それらを別々のtry-catchに配置する必要があり、これらのcatchブロックからの他のコードで例外が発生することはありません。

    {
       try
       {
          mustexec(); 
       }
       catch(){ }
    
       noexceptionexec();   
    
       try
       {
          mustexec();
       }
       catch() { }
    }
    
  • catch()のフォールスルーを最小限に抑える:ステートメントのセットが特定のExceptionのセットを引き起こす可能性があることが確実な場合は、外部試行の後に配置するのではなく、対応するExceptionのみを処理するようにそれらのコード行を配置する必要があります。したがって、上記の3番目のケース(混合パターン)が適切なケースになります。

    {
        try
        {
           exec(); //can cause ExceptionXYZ
        }
        catch(ExceptionABC){ }
        catch(ExceptionPQR){ }
        catch(ExceptionXYZ){ }
    }
    

上記は少し非効率的かもしれません

    {
        try
        {
           try
           {
              exec(); //can cause ExceptionXYZ
           }
           catch(ExceptionXYZ){ }
        }
        catch(ExceptionABC){ }
        catch(ExceptionPQR){ }
    }
4

9 に答える 9

7

Code1とCode2は同等ではありません。

try{
   exec1();
   exec2(); // if exec1 fails,  it is not executed
}catch(){}

try{
   exec1();
}catch(){}
try{
   exec2(); // if exec1 fails,  it is  executed
}catch(){}

そしてpoint3についてはそうです。コードを混在させることができます。

于 2013-02-05T13:34:21.450 に答える
3

ブロックを導入する場合はcatch、対応する例外をスローする可能性のあるコードにブロックを近づけることを好みます。これは、変数が使用される場所の近くで変数を宣言するのと同じ理由で、つまり読みやすさを向上させるためです。そのため、最初の例が明らかに望ましいです。

try/catchを一連のステートメントと組み合わせるとif、コードのリーダーが例外ハンドラーブロックの上で何が起こっているかをよりよく理解する必要があるため、それほどクリーンではありません。具体的には、例では、リーダーは1つの条件のみがtrue

クリーンアップコードのように例外ハンドラーを設定する必要がある場合もありますが、通常は、クリーンアップ中に第2レベルの例外を「ドロップ」し、第1レベルの例外のみを報告します。

于 2013-02-05T13:35:02.690 に答える
1

トライキャッチを1つだけ使用することもできます。以下を参照してください。

try {
    // some code that throws different exceptions
}
catch (Exception ex)            
{                
    if (ex is ExceptionA)
    {
        //do something
    }
    else if (ex is ExeptionB)
    {
        //do something
    }
}

等々

于 2013-02-05T13:34:03.497 に答える
1

ネストしない詩をネストすることは、設計上の決定です。例外から回復できる場合は、ネストは適切なようです。例外がターミナルの場合、ネストしないのは良いことのようです。次に例を示します。

try
{
   try
   {
     ... code that may throw RecoverableException1 or TerminalException
   }
   catch (RecoverableException1 exception)
   {
     ... recover.  Perhaps use default values and add a log entry.
   }


   try
   {
     ... code that may throw RecoverableException2 or TerminalException
   }
   catch (RecoverableException2 exception)
   {
     ... recover.  Perhaps use default values and add a log entry.
   }

}
catch (TerminalException exception)
{
  ... log the terminal exception and terminate.
}
于 2013-02-05T13:39:44.647 に答える
1

私はあなたの主な関心事は次のようにすべきだと思います:

  1. コードの正確さ、そして

  2. コードの読みやすさ。

他の人が指摘しているように、あなたの例の2つの形式は同じことを意味するものではありません。フォームの1つが他のフォームよりも正しい可能性があります。

等しく正しい2つのバージョンがある場合、最適なバージョンは最も読みやすいバージョンです。

このような人為的な例に基づいて、相対的な正確さや読みやすさを適切に判断することはできません。つまり、肝心なのは、この決定にはベストプラクティスのルールがないということです。


コードの2つのバージョンが等しく正しく、等しく読みやすいと仮定すると、複数のtry / catchブロックを使用する場合と、複数のハンドラーを使用する1つのtry / catchを使用する場合には、パフォーマンス上のわずかな利点があります。それはすべて、例外が処理されたときに何が起こるかにかかっています。複数のブロックがある場合、JVMは、一致する(またはそれらを使い果たす)ブロックが見つかるまで、各ブロックに対して順番にacatchと同等の処理を実行します。N個のブロックがある場合、実行する必要のあるテストは最大N個です。instanceofcatchcatch

ただし、違いは小さいことを強調する必要があります。特に、例外が例外的であると考える場合はそうです。つまり、ほとんどの場合、例外を処理する必要はありません。(そして、その仮定が正しくない場合、Java例外の最も高価な部分は通常、例外オブジェクトの構築であるため、おそらくより大きなパフォーマンスの問題が発生します。)

于 2013-02-05T14:02:27.377 に答える
0

あなたが書いたように、あなたは考えすぎています。http://docs.oracle.com/javase/tutorial/essential/exceptions/catch.htmlでOracleの公式ドキュメントを確認するだけで、例外を処理するための推奨される方法が明確にわかります。

try {

} catch (ExceptionType name) {

} catch (ExceptionType name) {

}
于 2013-02-05T13:34:29.177 に答える
0

例外がなかった場合、try/catchの開始と終了のCPU時間はゼロになります。メソッドにtry/catchブロックが多数ある場合、JVMは他の中で適切なキャッチを見つける必要があるため、適切なキャッチブロックに例外をディスパッチすると、CPUのコストがわずかに高くなる可能性があります。私にとって、あなたはここで考えすぎています。

于 2013-02-05T13:35:11.633 に答える
0

あなたが考慮すべき最初の(そしておそらく)唯一のことは、あなたができる最も単純で最も明確なコードを書く方法です。パフォーマンスの問題が発生する可能性のある動作中のアプリケーションがあり、測定可能な問題があると判断するためにプロファイルを作成した後でのみ。選択肢を比較して、あるものが別のものより優れているかどうかを確認できます。

パフォーマンスの問題があることを確認するまで、私はできる限り単純なコードを書くことに固執します。

注:最初のブロックで例外がスローされた場合、それが問題ではないかのように続行できると想定できますか?多くの場合、そうではなく、すべてのコードをtry/catchブロックでラップする方が理にかなっています。

于 2013-02-05T13:36:33.280 に答える
0

役立つはずのtry-with-resourcesを確認してください...

于 2015-09-25T10:42:40.800 に答える