マイクロサービス時代の Java 例外キャプチャ

1. e.printStackTrace() を使用せず、ログ出力を使用してみてください。


反例:

try{   // 必要なことを実行します  }catch(Exception e){   e.printStackTrace(); }





正例:​

try{   // 必要なことを実行します  }catch(Exception e){   log.info("プログラムに例外があります,{}",e); }





理由:​


printStackTrace() によって出力されるスタック ログはビジネス コード ログと交互に配置されるため、例外ログを確認するのは不便です。
e.printStackTrace() ステートメントによって生成された文字列には、スタック情報が記録されます。情報が長すぎて、文字列定数プールが配置されているメモリ ブロックにスペースがない場合、つまりメモリがいっぱいの場合、ユーザーのリクエストは行き詰まって〜

2. 例外は捕捉されましたが、特定の例外が出力されないため、問題をより適切に特定できない


反例:

try{   // やりたいことを実行します  }catch(Exception e){   log.info("あなたのプログラムには例外があります"); }




 

​正例:​

try{   // 必要なことを実行します  }catch(Exception e){   log.info("プログラムに例外があります。{}",e); }



​理由:​

反例では、例外が解放されず、その時点で問題のトラブルシューティングが困難になりますが、それは SQl エラーなのか、IO 例外なのか、それとも何か他のものなのでしょうか? したがって、例外はログに出力されるはずです~

3. 考えられるすべての
例外

反例:

public void test(){     try{         //...IOException をスローするコード呼び出し         //...SQLException をスローするコード呼び出し     }catch(Exception e){         //基本クラス Exception を使用して、考えられるすべての例外をキャッチします(存在する場合)このようなキャプチャはすべて、元の例外の有効な情報を失います。         log.info(“Exception in test,Exception:{}”, e);     } }









正例:​

public void test(){     try{         //...IOExceptionをスローするコード呼び出し         //...SQLExceptionをスローするコード呼び出し     } catch(IOException e){         //IOExceptionのみをキャッチ         log.info("IOException in test、例外:{ }", e);     }catch(SQLException e){         //SQLException のみをキャッチ         log.info("SQLException in test,Exception:{}", e);     } }











 

理由:

基本クラスの Exception を使用して、考えられるすべての例外を捕捉します。この方法で複数のレベルを捕捉すると、元の例外の有効な情報が失われます。

4. ストリーム リソースを閉じるには、必ずfinallyを使用するか、try-with-resourceを直接使用してください。

反例:

FileInputStream fdIn = null;
try {     fdIn = new FileInputStream(new File("/jay.txt"));     //ここでストリーム リソースを閉じますか? 何か問題ある?例外が発生した場合はどうなりますか?     fdIn.close(); } catch (FileNotFoundException e) {     log.error(e); } catch (IOException e) {     log.error(e); }








​正例1:​

次のように、finally を使用してストリーム リソースを閉じる必要があります。

FileInputStream fdIn = null;
{     fdIn = new FileInputStream(new File("/jay.txt")); を試してください。} catch (FileNotFoundException e) {     log.error(e); catch (IOException e) {     log.error(e); }最後に {     試してください {         if (fdIn != null) {             fdIn.close();     catch (IOException e) {         log.error(e);         } }     } }














​正例2:​

もちろん、Java7 が提供する自動リソース管理機能である JDK7 の新機能 try-with-resource も利用できます。


リソースは、プログラムの使用が終了したときに閉じる必要があるオブジェクトです。
try-with-resources は、宣言された各リソースがステートメントの最後に閉じられることを保証します。
リソースとして使用できるオブジェクトの種類は何ですか? java.lang.AutoCloseable インターフェースまたは java.io.Closeable インターフェースを実装したオブジェクトであれば問題ありません。

try (FileInputStream inputStream = new FileInputStream(new File("jay.txt")) {     // リソースを使用する   } catch (FileNotFoundException e) {     log.error(e); } catch (IOException e) {     log.error(e) ; }






​理由:​

finally または try-with-resource を使用しない場合、プログラムで例外が発生し、IO リソース フローが閉じられない場合、この IO リソースは常に占有されるため、他のユーザーはそれを使用できなくなります。 、リソースの無駄が発生します。


5. キャッチされた例外とスローされた例外は完全に一致する必要があります。そうでない場合、キャッチされた例外はスローされた例外の親クラスです。

反例:

//BizException は Exception のサブクラスです
public class BizException extends Exception {}
//親クラス Exception をスローします
public static void test() throws Exception {}


try {     test(); //コンパイル エラー} catch (BizException e) { //キャッチ例外のサブクラスは     log.error(e); }




​正例:​

//サブクラス例外をスローします
public static void test() throws BizException {}


{     test();を試してください。} catch (例外 e) {     log.error(e); }




 

6. キャッチされた例外は無視できません。少なくともログに記録してください。


反例:

public static void testIgnoreException() throws Exception {     try {                // 処理を実行します     } catch (Exception e) { // 通常、そのような例外はありません


    }
}


​正例:​

public static void testIgnoreException() {     try {         // 処理を実行します     } catch (Exception e) { // 通常、そのような例外はありません         log.error("この例外はここには表示されません,{}",e);      } }






理由:​

通常の状況では発生しない例外ですが、それをキャッチした場合は無視せず、少なくともログを作成してください〜

7. コード階層上の例外の感染に注意する (早期検出と早期処理)


反例:

public UserInfo queryUserInfoByUserId(Long userid) throw SQLException {     //ユーザー ID に従ってデータベースをクエリします}


 

​正例:​

public UserInfo queryUserInfoByUserId(Long userid) {     try{         //ユーザー ID に従ってデータベースをクエリします     }catch(SQLException e){         log.error("クエリ データベースが異常です、{}", e);     }finally{         //接続を閉じてリソースをクリーンアップします     } }









​理由:​

私たちのプロジェクトは通常、コードをアクション、サービス、Dao などのさまざまな階層構造に分割します。DAO 層で例外を処理している場合は、できるだけ早く処理します。SQLException が上向きにスローされても、上位層のコードはそのままです。 try catch で処理する必要があります。コードが汚染されます~


8. パッケージ例外をカスタマイズします。元の例外情報は破棄しないでください。 スローされる原因


多くの場合、1 つの例外をキャッチした後に別の例外をスローし、例外チェーンと呼ばれる元の例外の情報を保存したいと考えます。同社のフレームワークは、統一された例外処理を提供し、例外チェーンを使用しています。パッケージの例外をカスタマイズし、元の例外情報を破棄しません。そうしないと、トラブルシューティングが面倒になります。

反例:

public class TestChainException {     public void readFile() throws MyException{         try {             InputStream is = new FileInputStream("jay.txt");             Scanner in = new Scanner(is);             while (in.hasNext()) {                 System.out.println (in.next());             }         } catch (FileNotFoundException e) {             //e 例外情報を保存             throw new MyException("ファイルはどこですか");         }     }     public void invokeReadFile() throws MyException{         try {             readFile();         } catch (MyException e) {             //e 例外情報を保存

















            throw new MyException("ファイルが見つかりません");
        }
    }
    public static void main(String[] args) {         TestChainException t = new TestChainException();         try {             t.invokeReadFile();         } catch (MyException e) {             e.printStackTrace ();         }     } } //MyExceptionconstructor public MyException(String message) {         super(message);     }実行結果は以下の通りですが、Throwableな原因がないため、何が異常なのかのトラブルシューティングが困難です













正例:​

public class TestChainException {     public void readFile() throws MyException{         try {             InputStream is = new FileInputStream("jay.txt");             Scanner in = new Scanner(is);             while (in.hasNext()) {                 System.out.println (in.next());             }         } catch (FileNotFoundException e) {             //e 例外情報を保存             throw new MyException("ファイルはどこですか", e);         }     }     public void invokeReadFile() throws MyException{         try {             readFile( );         } catch (MyException e) {             //e 例外情報を保存

















            throw new MyException("ファイルが見つかりません", e);
        }
    }
    public static void main(String[] args) {         TestChainException t = new TestChainException();         try {             t.invokeReadFile();         } catch (MyException e) {             e .printStackTrace();         }     } } //MyException コンストラクターpublic MyException(String message, Throwable Cause) {         super(message, Cause);     }












 


9. 実行時例外 RuntimeException は、catch によって処理されるべきではなく、次のように事前にチェックされる必要があります。 NullPointerException 処理


反例:

try {   obj.method()  } catch (NullPointerException e) { ... }正例:





if (obj != null){    ...

 


10. 例外一致の順序に注意し、特定の例外を優先的にキャッチする


例外に一致する最初の catch ブロックのみが実行されるため、例外の一致順序に注意してください。NumberFormatException であることを確認したい場合は NumberFormatException をスローし、IllegalArgumentException である場合は IllegalArgumentException をスローします。

反例:

try {     doSomething("テスト例外"); catch (IllegalArgumentException e) {            log.error(e); catch (NumberFormatException e) {     log.error(e); }







正例:​

try {     doSomething("テスト例外"); catch (NumberFormatException e) {            log.error(e); catch (IllegalArgumentException e) {     log.error(e); }






 

理由:

NumberFormatException は IllegalArgumentException のサブクラスであるため、反例ではどの例外であっても IllegalArgumentException と一致し、それ以降は実行されないため、NumberFormatException であるかどうかはわかりません。したがって、特定の例外をキャッチすることを優先する必要があり、最初に NumberFormatException を置きます~
 

おすすめ

転載: blog.csdn.net/swebin/article/details/132437607