17

ExceptionJava では、スローされなくてもキャッチできるのに、そのサブクラスをキャッチできないのはなぜですか(「チェックされていない」 RuntimeExceptions とそのサブクラスを除く)。コード例:

class Test {
    public static void main(String[] args) {
        try {
            // do nothing
        } catch (Exception e) {
            // OK           
        }

        try {
            // do nothing
        } catch (IOException e) {
               // COMPILER ERROR: Unreachable catch block for IOException.
               //This exception is never thrown from the try statement body
        }       
    }
}

何か案は?

4

7 に答える 7

28

Aは、どのコードRuntimeExceptionでもスローされる可能性があります。つまり、コンパイラは、どの種類のコードがそれをスローできるかを簡単に予測できません。Aはブロックでキャッチできます。RuntimeExceptioncatch(Exception e)

IOExceptionただし、 はチェック済み例外です。それをスローするように宣言されているメソッド呼び出しのみがそうすることができます。コンパイラは、それをスローするように宣言されたメソッド呼び出しがない限り、発生する可能性がないことを (合理的に) 確信できます。

Java コンパイラは、単に「try ブロック内にコードがまったくない」状況を考慮しません。すべての合理的なシナリオでは、チェックされていない例外をスローする可能性のあるコードが存在するため、常にチェックされていない例外をキャッチできます。

JLSのセクション14.21から:

次の両方が true の場合、catch ブロック C に到達できます。

  • try ブロック内の一部の式または throw ステートメントは到達可能であり、型が catch 句 C のパラメーターに割り当て可能な例外をスローできます (式は、それを含む最も内側のステートメントが到達可能である場合に到達可能と見なされます)。
  • C のパラメーターの型が A のパラメーターの型と同じか、そのサブクラスであるような、try ステートメント内の以前の catch ブロック A はありません。

おそらくコンパイラは、最初のケースでは try ブロック内に式がないことを認識する必要があります...これはまだ到達できない catch 句のように見えます。

編集: コメントに記載されているように、セクション 14.20には次の内容が含まれています。

句がチェック済み例外タイプE1catchをキャッチしたが、次のすべてが成立するようなチェック済み例外タイプE2が存在しない場合、コンパイル時エラーになります。

  • E2 <: E1
  • 句に対応するtryブロックはE2catchをスローできます
  • catchすぐ外側の try ステートメントの前のブロックは、 E2またはE2のスーパータイプをキャッチしません。

E1がクラス Exception でない限り。

それがあなたが実際にファウルしているように見えますが、14.21 の到達不能な catch ブロックに関しては、仕様はそれほど明確ではありません。

于 2011-05-05T15:01:11.130 に答える
5

IO 例外は、コードに IOException をスローする何かがある可能性があるとコンパイラが予測した場合にのみキャッチできます。そのため、try ステートメントの本文から IO 例外がスローされないという警告が表示されます (try の本文には何もないため)。

于 2014-02-12T07:25:09.613 に答える
3

チェックされた例外の場合、それらをスローしているメソッドは「throws」キーワードでこの事実を明示的に述べる必要があるため、ブロックに「throws IOException」がない場合、コンパイラーはIOExceptionには不可能な情報を持っています投げられるので、捕まえた後は何をしても届かない。

于 2011-05-05T15:01:34.077 に答える
3

スローされないチェック例外をキャッチすることはできません。Exception未チェックの実行時例外Exceptionがスローされる可能性があるため、キャッチできます。

于 2011-05-05T15:01:37.650 に答える
1

IOExceptionIO 関連のコードによってのみスローされるチェック済み例外です。try ブロックは何もしないため、IO 関連は何も発生せず、IOExceptions がスローされることはありません。そのため、catch ブロックが実行されることはなく、コンパイラはそれを回避できません。あなたが言ったように、例外は、いつでも発生する可能性のあるチェックされていないランタイム例外を指す場合があります。これが、チェックされていない例外とチェックされている例外の主な違いであり、コンパイラがすべての実行時例外をキャッチするようにコードを強制しないのはそのためです。

于 2011-05-05T15:04:00.670 に答える
0

単に Java は、任意のコード行がジェネリックExceptionorをスローできると想定していますThrowableOutOfMemoryExceptionこれはErrorかなりExceptionです。NPE についても同様です。

IOExceptionマネージ コードによってのみスローされる可能性のある特定の例外であるため、catch ブロックに I/O 呼び出しがない場合、コンパイラはそれをキャッチする機会がありません。

C# の世界と比較すると、C# ではそのようなコードはコンパイルされますが、何もしなければ catch ブロックに到達しないため、概念的な間違いになります。ReSharper などのツールは、それについて警告することができます。

于 2011-05-05T15:01:03.237 に答える