面接:Javaで異常に関するよくある質問

16197 ワード

文書ディレクトリ
  • 前言
  • 一、運行異常と検査異常の違いは何ですか?
  • 二、異常遵守原則はどれらがありますか?
  • 三、JAVAにおけるtry、catch、finally帯returnの実行順序総括
  • 1.tryにreturn
  • がある
  • 2.returnは参照タイプ
  • を返す
  • 3.catchにreturn
  • が付いています
  • 4.finallyにreturn
  • がある
  • 四、総括

  • 前言
    最近は面接中にJavaの異常を聞かれることが多いので、ここで簡単にまとめてみましょう
    一、運行異常と受検異常の違いは何ですか.
    異常はプログラムの実行中に発生する可能性のある非正常な状態を表し、実行時の異常は仮想マシンの通常の操作で発生する可能性のある異常を表し、プログラムの設計に問題がなければ通常発生しない一般的な実行エラーである.
    チェックされた例外は、プログラムの実行のコンテキスト環境に関連しており、プログラムの設計が間違っていなくても、使用の問題によって発生する可能性があります.
    Javaコンパイラでは、メソッドが検出される可能性のある例外を宣言する必要がありますが、取得されていないランタイム例外を宣言する必要はありません.
    二、異常遵守原則はどれらがありますか.
    例外は継承と同様に,オブジェクト向けプログラミングでよく乱用されるものであり,Effective Javaでは例外の使用について以下の例外遵守原則を与えている.
  • 異常処理を通常の制御フローに使用しない(設計の良いAPIは、その呼び出し者に通常の制御フローのために異常を使用するように強制すべきではない)
  • .
  • 復元可能な場合には被検異常、プログラミングエラーにはランタイム異常
  • を用いる.
  • 不必要な被検異常の使用を避ける(いくつかの状態検出手段によって異常の発生を避けることができる)
  • .
  • 優先使用基準の異常
  • メソッドごとに投げ出す例外には、ドキュメント
  • が必要です.
  • 異常な原子性を保つ
  • catchでキャプチャされた異常
  • を無視しないでください.
    三、JAVAにおけるtry、catch、finallyベルトreturnの実行順序のまとめ
    異常処理ではtry,catch,finallyの実行順は,順番に実行されることが知られている.すなわち、tryに異常がなければtry→finallyの順であり、tryに異常があればtry→catch→finallyの順である.しかしtry,catch,finallyにreturnを加えると,いくつかの異なる場合があり,以下ではそれぞれ説明する.最後までジャンプしてまとめを直接見ることもできます.
    1.tryにreturn付き
    コードは次のとおりです(例).
     private int testReturn1() {
         
     2         int i = 1;
     3         try {
         
     4             i++;
     5             System.out.println("try:" + i);
     6             return i;
     7         } catch (Exception e) {
         
     8             i++;
     9             System.out.println("catch:" + i);
    10         } finally {
         
    11             i++;
    12             System.out.println("finally:" + i);
    13         }
    14         return i;
    15     }
    

    出力:try:2 finally:3 return:2
    tryにreturnが付いている場合は、まずreturn前のコードを実行し、その後、returnが必要な情報を一時的に保存してからfinallyのコードを実行し、最後にreturnで前に保存した情報を返すからです.したがって,ここでメソッドが返す値はfinallyで計算した3ではなくtryで計算した2である.しかし、もう一つの例を見てみましょう.
    2.returnは参照タイプを返す
    コードは次のとおりです(例).
     private List<Integer> testReturn2() {
         
     2         List<Integer> list = new ArrayList<>();
     3         try {
         
     4             list.add(1);
     5             System.out.println("try:" + list);
     6             return list;
     7         } catch (Exception e) {
         
     8             list.add(2);
     9             System.out.println("catch:" + list);
    10         } finally {
         
    11             list.add(3);
    12             System.out.println("finally:" + list);
    13         }
    14         return list;
    15     }
    

    出力:try:[1]finally:[1,3]return:[1,3]
    この例を見てみると、returnといえば返す必要がある情報を一時的に保存し、finallyの影響を受けないのに、なぜここに変化があるのかという問題があるかもしれません.実は問題はパラメータタイプで、前の例では基本タイプを使用していましたが、ここでは参照タイプを使用しています.リストに格納されているのは変数そのものではなく、変数のアドレスなので、finallyがアドレスで変数を変更すると、メソッドの戻り値に影響します.
    3.catchにreturn付き
    コードは次のとおりです(例).
     private int testReturn3() {
         
     2         int i = 1;
     3         try {
         
     4             i++;
     5             System.out.println("try:" + i);
     6             int x = i / 0 ;
     7         } catch (Exception e) {
         
     8             i++;
     9             System.out.println("catch:" + i);
    10             return i;
    11         } finally {
         
    12             i++;
    13             System.out.println("finally:" + i);
    14         }
    15         return i;
    16     }
    

    出力:try:2 catch:3 finally:4 return:3
    catchのreturnはtryと同様に、return前のコードを先に実行し、その後returnが必要な情報を一時的に保存し、finallyのコードを実行し、最後にreturnで前に保存した情報を返す.したがって,ここでメソッドが返す値はfinallyで計算した4ではなくtry,catchで累積計算した3である.
    4.finallyにreturn付き
    コードは次のとおりです(例).
     private int testReturn4() {
         
     2         int i = 1;
     3         try {
         
     4             i++;
     5             System.out.println("try:" + i);
     6             return i;
     7         } catch (Exception e) {
         
     8             i++;
     9             System.out.println("catch:" + i);
    10             return i;
    11         } finally {
         
    12             i++;
    13             System.out.println("finally:" + i);
    14             return i;
    15         }
    16     }
    

    出力:try:2 finally:3 return:3
    finallyにreturnがある場合、tryのreturnは失効し、finallyのreturnを実行した後、tryのreturnは実行されません.この書き方では、コンパイルはコンパイルできますが、コンパイラは警告を与えるのでfinallyにreturnを書くことをお勧めしません.これはプログラムの完全性を破壊し、finallyに異常が発生するとcatchの異常が上書きされます.
    四、まとめ
    1、finallyのコードは常に実行されます.
    2、try、catchにreturnがある場合もfinallyが実行されます.returnの場合、戻り値のタイプがfinallyのコードの影響を受けるかどうかに注意してください.
    3、finallyにreturnがある場合、finallyで直接終了し、try、catchのreturnが失効する.