原文: https://howtodoinjava.com/java7/java-suppressed-exceptions/
顾名思义, 被抑制的异常是在代码中引发的异常,但是以某种方式被忽略了。 如果您记得try-catch-finally块的执行顺序以及它们如何返回任何值或异常,那么您会记得,如果try中引发了异常,则也将抑制finally块中引发的异常。
在 Java 7 之前的版本中,您通过记录日志了解了这些异常(如果已实现),但是一旦finally块结束,您就无法控制这些类型的异常。
好吧,借助 Java 7 中的新特性,您还可以控制这些受抑制的异常。
Table of contents1\. What are suppressed exceptions?2\. Suppressed exception example3\. Demonstration in different scenarios
1. 什么是禁止的异常?
在 Java 7 中,遇到抑制异常的最常见用例是 try-with-resources 语句。 当我们在try块中遇到异常时,应用程序将尝试关闭资源。 如果它遇到关闭AutoCloseable资源时可能发生的多个异常,则会将其他异常作为抑制的异常附加到主要异常上。
为了支持抑制的异常,在 JDK 7 中向Throwable类(Exception和Error类的父级)添加了新的构造器和两个新方法。
Throwable.getSupressed(); // Returns Throwable[]Throwable.addSupressed(aThrowable);
2. 抑制异常的例子
例如,在写入输出流时,可以从try块引发一个异常,当try-with-resources语句尝试关闭流时,可以从该异常中引发最多两个异常。
如果从try块引发一个异常,并且从try-with-resources语句引发一个或多个异常,则将从try-with-resources语句引发的那些异常抑制,并且由该块引发的异常由closeStream()方法抛出。
您可以通过从try块引发的异常中调用Throwable.getSuppressed()方法来检索这些受抑制的异常。
3. 在不同情况下的示例
例如,我正在编写一个自动关闭的资源(即DirtyResource.java),无论我们尝试访问它还是关闭它,它都会引发异常。 这样,当以不同方式访问时,我们将能够看到不同的行为。
public class DirtyResource implements AutoCloseable{/*** Need to call this method if you want to access this resource* @throws RuntimeException no matter how you call this method* */public void accessResource(){throw new RuntimeException("I wanted to access this resource. Bad luck. Its dirty resource !!!");}/*** The overridden closure method from AutoCloseable interface* @throws Exception which is thrown during closure of this dirty resource* */@Overridepublic void close() throws Exception{throw new NullPointerException("Remember me. I am your worst nightmare !! I am Null pointer exception !!");}}
3.1 抑制异常之前的特性
package com.howtodoinjava.demo.core;import static java.lang.System.err;public class SuppressedExceptionDemoWithTryFinallyPrevious{/*** Executable member function demonstrating suppressed exceptions* One exception is lost if not added in suppressed exceptions list*/public static void memberFunction() throws Exception{DirtyResource resource= new DirtyResource();try{resource.accessResource();}finally{resource.close();}}public static void main(String[] arguments) throws Exception{try{memberFunction();}catch(Exception ex){err.println("Exception encountered: " + ex.toString());final Throwable[] suppressedExceptions = ex.getSuppressed();final int numSuppressed = suppressedExceptions.length;if (numSuppressed > 0){err.println("tThere are " + numSuppressed + " suppressed exceptions:");for (final Throwable exception : suppressedExceptions){err.println("tt" + exception.toString());}}}}}Output:Exception encountered: java.lang.NullPointerException: Remember me. I am your worst nightmare !! I am Null pointer exception !!
如您所见,仅捕获了一个异常,而第二个RuntimeException被抑制。
3.2 在 Java 7 中抑制异常之后
package com.howtodoinjava.demo.core;import static java.lang.System.err;public class SuppressedExceptionDemoWithTryFinallyNew{/*** Executable member function demonstrating suppressed exceptions* Suppressed expression is added back in primary exception*/public static void memberFunction() throws Exception{Throwable th = null;DirtyResource resource= new DirtyResource();try{resource.accessResource();}catch(Exception e){th = e;}finally{try{resource.close();}catch(Exception e){if(th != null){e.addSuppressed(th); //Add to primary exceptionthrow e;}}}}/*** Executable function demonstrating suppressed exceptions.*/public static void main(String[] arguments) throws Exception{try{memberFunction();}catch(Exception ex){err.println("Exception encountered: " + ex.toString());final Throwable[] suppressedExceptions = ex.getSuppressed();final int numSuppressed = suppressedExceptions.length;if (numSuppressed > 0){err.println("tThere are " + numSuppressed + " suppressed exceptions:");for (final Throwable exception : suppressedExceptions){err.println("tt" + exception.toString());}}}}}Output:Exception encountered: java.lang.NullPointerException: Remember me. I am your worst nightmare !! I am Null pointer exception !!There are 1 suppressed exceptions:java.lang.RuntimeException: I wanted to access this resource. Bad luck. Its dirty resource !!!
在这里,在catch块中,我们可以访问两个异常。 一个作为主要异常,第二个作为受抑制异常。
3.3 成员函数中的try-with-resource块并捕获异常
package com.howtodoinjava.demo.core;import static java.lang.System.err;public class SuppressedExceptionDemoWithTryCatch{public static void memberFunction() throws Exception{try (DirtyResource resource= new DirtyResource()){resource.accessResource();}}/*** Executable member function demonstrating suppressed exceptions using try-with-resources*/public static void main(String[] arguments) throws Exception{try{memberFunction();}catch(Exception ex){err.println("Exception encountered: " + ex.toString());final Throwable[] suppressedExceptions = ex.getSuppressed();final int numSuppressed = suppressedExceptions.length;if (numSuppressed > 0){err.println("tThere are " + numSuppressed + " suppressed exceptions:");for (final Throwable exception : suppressedExceptions){err.println("tt" + exception.toString());}}}}}Output:Exception encountered: java.lang.RuntimeException: I wanted to access this resource. Bad luck. Its dirty resource !!!There are 1 suppressed exceptions:java.lang.NullPointerException: Remember me. I am your worst nightmare !! I am Null pointer exception !!
太好了! 在成员函数中使用try-with-resource时,我们能够看到这两种异常。
3.4 默认try-with-resource块
package com.howtodoinjava.demo.core;public class SuppressedExceptionDemoWithTryWithResource{/*** Demonstrating suppressed exceptions using try-with-resources*/public static void main(String[] arguments) throws Exception{try (DirtyResource resource= new DirtyResource()){resource.accessResource();}}}Output:Exception in thread "main" java.lang.RuntimeException: I wanted to access this resource. Bad luck. Its dirty resource !!!at DirtyResource.accessResource(DirtyResource.java:9)at SuppressedExceptionDemoWithTryWithResource.main(SuppressedExceptionDemoWithTryWithResource.java:12)Suppressed: java.lang.NullPointerException: Remember me. I am your worst nightmare !! I am Null pointer exception !!at DirtyResource.close(DirtyResource.java:19)at SuppressedExceptionDemoWithTryWithResource.main(SuppressedExceptionDemoWithTryWithResource.java:13)
好吧,非常高兴看到包含抑制异常的完整信息的输出。
学习愉快!
