answer に対する 末尾呼び出しの最適化に関する質問 に関するコメント(ユーザーによる soc )Java 7には、「ARMの追加」のために、「抑制された例外」と呼ばれる新しい機能があります(ARM CPUsのサポート?)。
このコンテキストでの「抑制された例外」とは何ですか?他のコンテキストでは、「抑制された例外」は、キャッチされて無視された例外です(まれに良い考えです)。これは明らかに異なるものです。
コメンターが言及しているのは、既存のコンテキストで try-with-resources ブロックの暗黙的なfinally
ブロック内でスローされた場合に半無視される例外であると思いますtry
ブロックからスローされる例外:
Try-with-resourcesステートメントに関連付けられたコードブロックから例外をスローできます。 writeToFileZipFileContentsの例では、tryブロックから例外をスローできます。また、ZipFileオブジェクトとBufferedWriterオブジェクトを閉じようとしたときに、try-with-resourcesステートメントから最大2つの例外をスローできます。 tryブロックから例外がスローされ、try-with-resourcesステートメントから1つ以上の例外がスローされる場合、try-with-resourcesステートメントからスローされる例外は抑制され、ブロックによってスローされる例外が1つになります。 writeToFileZipFileContentsメソッドによってスローされます。 tryブロックによってスローされた例外からThrowable.getSuppressedメソッドを呼び出すことで、これらの抑制された例外を取得できます。
(リンクされたページから「抑制された例外」と呼ばれるセクションを引用しています。)
Jonの答えの引用を明確にするために、メソッドによって(実行ごとに)スローされる例外は1つだけですが、try-with-resources
の場合、複数の例外がスローされる可能性があります。たとえば、1つはブロック内でスローされ、もう1つはtry-with-resources
によって提供される暗黙のfinally
からスローされます。
コンパイラは、これらのどれを「実際に」スローするかを決定する必要があります。暗黙的なコード(try
ブロック)によってスローされる例外ではなく、明示的なコード(finally
ブロック内のコード)で発生した例外をスローすることを選択します。したがって、暗黙ブロックでスローされた例外は抑制されます(無視されます)。これは、複数の例外の場合にのみ発生します。
Java7より前。コードには例外がスローされますが、どういうわけか無視されました。
例えば。)
public class SuppressedExceptions {
public static void main(String[] args) throws Exception {
try {
callTryFinallyBlock();
} catch (Exception e) {
e.printStackTrace(); **//Only Finally Exception is Caught**
}
}
private static void callTryFinallyBlock() throws Exception {
try
{
throw new TryException(); **//This is lost**
}
finally
{
FinallyException fEx = new FinallyException();
throw fEx;
}
}
}
class TryException extends Exception {
}
class FinallyException extends Exception {
}
新しいコンストラクターと2つの新しいメソッドがJDK 7のThrowableクラスに追加されました。これらは次のとおりです。
Throwable.getSupressed(); // Returns Throwable[]
Throwable.addSupressed(aThrowable);
この新しいアプローチにより、抑制された例外も処理できます。
public class SuppressedExceptions {
public static void main(String[] args) throws Exception {
try {
callTryFinallyBlock();
} catch (Exception e) {
e.printStackTrace();
for(Throwable t: e.getSuppressed())
{
t.printStackTrace();
}
}
}
private static void callTryFinallyBlock() throws Exception {
Throwable t = null;
try
{
throw new TryException();
}
catch (Exception e) {
t = e;
}
finally
{
FinallyException fEx = new FinallyException();
if(t != null)fEx.addSuppressed(t);
throw fEx;
}
}
}
class TryException extends Exception {
}
class FinallyException extends Exception {
}
Java7では、try-with-resources; AutoCloseable :: close()の例外は、try例外とともにデフォルトで抑制された例外として追加されます。
また、これは 連鎖例外 とは異なることに注意してください(JDK 1.4で導入され、例外間の因果関係を簡単に追跡できるようにすることを目的としていました)。
抑制された例外 は、try-with-resourcesステートメント内で発生する追加の例外です( Java 7 で導入) AutoCloseable
リソースが閉じられています。AutoCloseable
リソースを閉じるときに複数の例外が発生する可能性があるため、追加の例外が 抑制された例外としてのプライマリ例外 に付加されます。
Try-with-resourcesサンプルコードのバイトコードを見ると、標準の JVM例外ハンドラ がtry-with-resourcesセマンティクスに対応するために使用されています。
以下のコードを認める:
public class MultipleExceptionsExample {
static class IOManip implements Closeable{
@Override
public void close() {
throw new RuntimeException("from IOManip.close");
}
}
public static void main(String[] args) {
try(IOManip ioManip = new IOManip()){
throw new RuntimeException("from try!");
}catch(Exception e){
throw new RuntimeException("from catch!");
}finally{
throw new RuntimeException("from finally!");
}
}
}
すべての行で次のようになります:Java.lang.RuntimeException: from finally!
finally
ブロックを削除すると、次の結果が得られます:Java.lang.RuntimeException: from catch!
catch
ブロックを削除すると、次の結果が得られます。
Exception in thread "main" Java.lang.RuntimeException: from try!
Suppressed: Java.lang.RuntimeException: from IOManip.close
これは「連鎖例外機能」に関係していると思います。スタックトレースが進化するにつれて、この機能による例外の処理方法に影響します。連鎖した例外のグループの一部である時間の経過した例外は抑制できます。詳細については、 Throwable documentation をご覧ください。
ARM-自動リソース管理(Java 7)以降導入)
非常に単純な例を取り上げます
_static String readFirstLineFromFileWithFinallyBlock(String path)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
}
_
readLine()
関数がExceptionをスローし、さらにclose()
function [in finally block]が例外をスローした場合、後者の優先度が高くなり、呼び出し元の関数にスローバックされます。この場合、Exception thrown by the readLine() method is ignored/suppressed
。例外の原因となっている例外を連鎖させ、finallyブロックから例外を再スローできます。
抑制された例外を取得する_Java 7
_機能が提供されているため。キャッチされたスロー可能オブジェクトでpublic final Java.lang.Throwable[] getSuppressed()
関数を呼び出して、抑制された例外を表示できます。
例えば.
_static String readFirstLineFromFileWithFinallyBlock(String path)
throws Exception {
try (BufferedReader br = new BufferedReader(new FileReader(path));) {
return br.readLine();
}
}
_
br.readLine();
行が_Exception1
_をスローし、リソースを閉じるときに_Exception2
_がスローされる場合Exception1は、Exception2を抑制します。
ここで注意すべき点はほとんどありません-
次の投稿で、コードスニペットと出力を使用して、考えられるシナリオのほとんどをコンパイルしました。
Java 7 で抑制された例外
お役に立てば幸いです。
Java 6でも例外を抑制することができます(少し手間がかかります)、
Java 1.6およびJava 1.7。実装を見つけることができます here
必要なのは、電話するだけです:
public static <T extends Throwable> T suppress(final T t, final Throwable suppressed)
例外を抑制する
public static Throwable [] getSuppressed(final Throwable t) {
誰かがまだJava 1.6を使用している場合、例外の抑制された例外を取得する