Java では、例外をスローする可能性のあるステートメントはすべてtry ... catch
キャッチできます。例外を引き起こす可能性のあるステートメントをtry { ... }
中央に配置し、catch を使用して対応するクラスException
とそのサブクラスをキャプチャします。
複数の catch ステートメント
複数のcatch
ステートメントを使用して、それぞれがcatch
対応するException
クラスとそのサブクラスをキャプチャすることができます。JVM
例外がキャッチされた後、catch
ステートメントは上から下に照合され、特定の照合の後、コード ブロックcatch
が実行され、その後照合は続行されません。catch
簡単に言えば、catch
複数のステートメントのうち 1 つだけを実行できます。例えば:
public static void main(String[] args) {
try {
process1();
process2();
process3();
} catch (IOException e) {
System.out.println(e);
} catch (NumberFormatException e) {
System.out.println(e);
}
}
複数ある場合catch
、catch
順序は非常に重要です。サブクラスを最初に記述する必要があります。例えば:
public static void main(String[] args) {
try {
process1();
process2();
process3();
} catch (IOException e) {
System.out.println("IO error");
} catch (UnsupportedEncodingException e) {
// 永远捕获不到
System.out.println("Bad encoding");
}
}
上記のコードの場合、UnsupportedEncodingException
例外は のIOException
サブクラスであるため、例外はキャッチされません。例外がスローされるとUnsupportedEncodingException
、それがcatch (IOException e) { ... }
捕捉されて実行されます。
したがって、正しい書き方はサブクラスを前に置くことです。
public static void main(String[] args) {
try {
process1();
process2();
process3();
} catch (UnsupportedEncodingException e) {
System.out.println("Bad encoding");
} catch (IOException e) {
System.out.println("IO error");
}
}
finally
ステートメント
例外が発生するかどうかに関係なく、クリーンアップなどのステートメントを実行したい場合、どのように記述すればよいでしょうか?
実行ステートメントは複数回記述することができます。通常どおり実行されるステートメントを配置しtry
、catch
それぞれを再度記述します。例えば:
public static void main(String[] args) {
try {
process1();
process2();
process3();
System.out.println("END");
} catch (UnsupportedEncodingException e) {
System.out.println("Bad encoding");
System.out.println("END");
} catch (IOException e) {
System.out.println("IO error");
System.out.println("END");
}
}
上記のコードは、例外が発生したかどうかに関係なく、System.out.println("END");
このステートメントを実行します。
では、これらの重複コードを削除するにはどうすればよいでしょうか? Java的try ... catch
このメカニズムは、エラーの有無にかかわらず実行されることが保証されたfinally
ステートメント、finally
つまりステートメントのブロックも提供します。上記のコードは次のように書き換えることができます。
public static void main(String[] args) {
try {
process1();
process2();
process3();
} catch (UnsupportedEncodingException e) {
System.out.println("Bad encoding");
} catch (IOException e) {
System.out.println("IO error");
} finally {
System.out.println("END");
}
}
finally
いくつかの機能があることに注意してください。
finally
ステートメントは必須ではなく、記述してもしなくても構いません。
finally
ステートメントは常に最後に実行されます。
例外が発生しない場合、ステートメント ブロックは通常どおり実行されtry { ... }
、その後実行されますfinally
。例外が発生した場合は、try { ... }
ステートメント ブロックの実行を中断し、一致する catch ステートメント ブロックの実行にジャンプし、最後にそれを実行しますfinally
。
finally
一部のコードを確実に実行するために使用されていることがわかります。
場合によっては、何も存在せずcatch
、try ... finally
構造体のみを使用することもできます。例えば:
void process(String file) throws IOException {
try {
...
} finally {
System.out.println("END");
}
}
このメソッドではスローされる可能性のある例外を宣言しているため、 を記述する必要はありませんcatch
。
複数の例外のキャッチ
一部の例外の処理ロジックは同じでも、例外自体に継承関係がない場合は、複数の catch 句を記述する必要があります。
public static void main(String[] args) {
try {
process1();
process2();
process3();
} catch (IOException e) {
System.out.println("Bad input");
} catch (NumberFormatException e) {
System.out.println("Bad input");
} catch (Exception e) {
System.out.println("Unknown error");
}
}
IOException
合計を処理するコードはNumberFormatException
同じであるため、2 つの使用方法を組み合わせることができます。
public static void main(String[] args) {
try {
process1();
process2();
process3();
} catch (IOException | NumberFormatException e) {
// IOException或NumberFormatException
System.out.println("Bad input");
} catch (Exception e) {
System.out.println("Unknown error");
}
}
まとめ
使用する場合try ... catch ... finally
:
複数のcatch
ステートメントの一致順序は非常に重要であり、サブクラスを最初に配置する必要があります。
finally
このステートメントは、例外の有無にかかわらず実行されることを保証します。これはオプションです。
ステートメントcatch
は複数の非継承例外と一致することもあります。