Java 什么是被抑制的异常?

Java 什么是被抑制的异常?,java,exception,exception-handling,try-with-resources,Java,Exception,Exception Handling,Try With Resources,一篇关于to的评论(由用户)提到Java7有一个新特性,称为“抑制异常”,因为“添加了ARM”(支持ARM CPU?) 在这种情况下,“被抑制的例外”是什么?在其他情况下,“被抑制的异常”将是一个被捕获然后被忽略的异常(很少是一个好主意);这显然是不同的。我相信评论者所指的是一个异常,当它在块的隐式finally块中抛出时,在从try块抛出现有异常的上下文中,该异常被半忽略: 可以从与try with resources语句关联的代码块中引发异常。在示例writeToFileZipFileCon

一篇关于to的评论(由用户)提到Java7有一个新特性,称为“抑制异常”,因为“添加了ARM”(支持ARM CPU?)


在这种情况下,“被抑制的例外”是什么?在其他情况下,“被抑制的异常”将是一个被捕获然后被忽略的异常(很少是一个好主意);这显然是不同的。

我相信评论者所指的是一个异常,当它在块的隐式
finally
块中抛出时,在从
try
块抛出现有异常的上下文中,该异常被半忽略:

可以从与try with resources语句关联的代码块中引发异常。在示例writeToFileZipFileContents中,可以从try块引发异常,当try with resources语句尝试关闭ZipFile和BufferedWriter对象时,最多可以从try with resources语句引发两个异常。如果从try块引发异常,并且从try with resources语句引发一个或多个异常,则从try with resources语句引发的异常将被抑制,并且该块引发的异常是writeToFileZipFileContents方法引发的异常。通过从try块抛出的异常调用Throwable.getsupprested方法,可以检索这些被抑制的异常


(这引用了链接页面中名为“抑制的异常”的部分。)

为了澄清Jon回答中的引用,一个方法(每次执行)只能引发一个异常,但在
尝试使用资源的情况下,可以引发多个异常。例如,一个可能在块中抛出,另一个可能从
try with resources
提供的隐式
finally
中抛出

编译器必须确定要“真正”抛出哪一个。它选择抛出显式代码(try
块中的代码)中引发的异常,而不是隐式代码(finally块)引发的异常。因此,隐式块中引发的异常将被抑制(忽略)。这仅在出现多个异常的情况下发生。

是资源关闭时try with resources语句()中发生的其他异常。由于关闭可自动关闭的
资源时可能会发生多个异常,因此会将其他异常附加到一个


查看一段try-with-resources示例代码的字节码,标准用于适应try-with-resources语义。

我认为这与“链式异常功能”有关。随着堆栈跟踪的发展,它将影响此工具处理异常的方式。随着时间的推移,作为链接异常组一部分的异常会被抑制。查看了解更多详细信息。

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()
函数抛出异常,然后甚至
close()
函数[in finally block]抛出异常,则后者被赋予更高的优先级,并被抛出回调用函数。在这种情况下,readLine()方法引发的
异常被忽略/抑制。您可以将导致异常的异常链接到您的异常中,并从finally块重新引发您的异常

由于
java7
提供了检索被抑制异常的功能。您可以对捕获的Throwable对象调用
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()
line抛出
Exception1
,然后假设在关闭资源时抛出
Exception2
[想象这发生在try with resource语句创建的隐式finally块中],然后Exception1抑制Exception2

这里需要注意的几点:

  • 如果try with资源块抛出异常,即在资源实例化时,则try块将不会执行,并将抛出相同的异常
  • 如果资源实例化成功,try块抛出异常,并且在关闭资源时抛出异常,那么在关闭资源时抛出的异常将被try块抛出的异常抑制
  • 若您提供显式finally块,并且从该块抛出异常,则它将抑制所有其他异常。(此显式finally块在资源关闭后执行)
  • 在下面的文章中,我用代码片段和输出编译了大多数可能的场景


    希望这会有所帮助。

    您也可以抑制Java 6中的异常(其中涉及一些小技巧)

    我创建了一个实用程序,可以透明地处理Java1.6和Java1.7中的异常抑制。您可以找到实现

    您只需拨打:

    public static <T extends Throwable> T suppress(final T t, final Throwable suppressed) 
    

    获取异常的抑制异常,以防任何人在Java7之前仍使用Java1.6;代码中有抛出的异常,但不知何故被忽略了

    e、 g.)

    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中尝试使用资源;AutoCloseable::close()处的异常 默认情况下,与try异常一起添加为抑制异常


    还意识到这与(JDK 1.4中引入的)不同,旨在使您能够轻松跟踪异常之间的因果关系。

    承认以下代码:

    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

    删除
    最后
    块,您将获得:
    java.lang.RuntimeException:来自catch<
    
    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 {
    }
    
    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!");
           }
       }
    }
    
    Exception in thread "main" java.lang.RuntimeException: from try!
        Suppressed: java.lang.RuntimeException: from IOManip.close