Java例外処理:「正しい」がコンパイラによって文法エラーとみなされるプログラムをどのように書くか


文章のタイトルは矛盾しているように見えるが、私は「正しい」の二文字に引用符を打った.Java例外処理(Exception Handling)に関するいくつかの知識点の例を見てみましょう.
次のプログラムを見てください.メソッドpleaseThrowは、Exceptionのインスタンスを受け入れ、そのインスタンスを簡単に放出します.このメソッドを呼び出すと、SQLExceptionのインスタンスが転送されます.pleaseThrowの呼び出しがtry catchブロックに包まれているので、
質問:plesseThrowメソッドが投げ出したSQLExceptionはcatchに住むことに成功しますか?
public class ExceptionForQuiz {

      private void pleaseThrow(final Exception t) throws T {

             throw (T) t;

      }

     public static void main(final String[] args) {

          try {

               new ExceptionForQuiz().pleaseThrow(new SQLException());

          }

         catch( final SQLException ex){

              System.out.println("Jerry print");

              ex.printStackTrace();

        }

}

}

答え:上のコードは文法の間違いがあって、コンパイルすることができません!
私たちは一歩一歩分析します.
JavaクラスExceptionForQuizでは、T extends Exceptionとは、この汎用クラスがインスタンス化されたときに入力されるタイプパラメータTがExceptionおよびそのサブクラスであることを意味する汎用構文を使用しています.
クラスExceptionForQuizをインスタンス化したときに入力したタイプパラメータはRuntimeExceptionです.
RuntimeExceptionはJavaではUnchecked例外であり,1つのメソッドが実行されるとRuntimeExceptionが投げ出される可能性があるとしても,開発者がメソッドの前にコードで明示的に宣言する必要はない.
JDK RuntimeExceptionの注釈を見てはっきり言った:Unchecked exceptions do NOT need to be declared in a method or constructor's clause if they can be thrown by the execution of the method or constructor.
この作者Frank Yellinはきっと大牛に違いない.
汎用型はJava 1.5バージョンで導入された概念であるため、汎用型についてはコードコンパイル段階にのみ存在し、コンパイル後のコードには汎用型に関する情報が消去されるタイプ消去の概念がある.たとえば、従来の汎用クラスのタイプパラメータ部分に上限が指定されていない場合、このような書き方は、通常のObjectタイプに変換されます.上限が指定されている場合、タイプパラメータはタイプ上限に置き換えられます.
簡略化のために、コードのtry catchブロックを削除します.
次に、ExceptionForQuiz.classから逆コンパイルしたコードを示します.
上の図から,方法pleaseThrowと雷ExceptionForQuizの汎用パラメータRuntimeExceptionが消去されていることが観察された.pleaseThrowという方法で投げ出すことができる異常タイプはすでに消去されてExceptionとなっている.
Javapを使用してコンパイルされたバイトコードを観察すると、タイプパラメータRuntimeExceptionが消去されていることがわかります.
2番目の赤いハイライトを見てください:Exceptions:throw java.lang.Exception
コンパイラがどのようなエラーメッセージを報告するか見てみましょう:Unreachable catch block for SQLException.This exception is never thrown from the try statement body.
例外タイプ消去の事実によれば、このエラーメッセージは合理的であり、pleaseThrowメソッドの宣言は現在、Exceptionタイプの例外しか投げ出せないため、14行目のcatchはSQLExceptionタイプの例外を永遠に受信できないため、コンパイラはエラーを投げ出す.
このコンパイラエラーを解消するにはどうすればいいですか?14行目のSQLExceptionをRuntimeExceptionに変更すればよい.
しかし、これでは構文エラーは解消されますが、メソッドpleaseThrowが投げ出したSQLExceptionはcatchに住めず、ランタイムエラーを報告します.
どうやってpleaseThrowが投げ出したSQLExceptionもcatch文で受け止めますか?14行目のRuntimeExceptionをすべての例外のスーパークラス:Exceptionに変更します.
もう一度実行します.今回は文法エラーも実行時エラーもありません.SQLExceptionは14行目のcatch文にスナップされました.
Jerryのオリジナル技術の記事をもっと入手するには、「汪子熙」という公衆番号に注目するか、次のQRコードをスキャンしてください.