# Java 抑制异常示例

> 原文： [https://howtodoinjava.com/java7/java-suppressed-exceptions/](https://howtodoinjava.com/java7/java-suppressed-exceptions/)

顾名思义， [**被抑制的异常**](https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html#suppressed-exceptions "suppressed-exceptions")是在代码中引发的异常，但是以某种方式被忽略了。 如果您记得[`try-catch-finally`](https://howtodoinjava.com/java7/automatic-resource-management-with-try-with-resources-in-java-7/)块的执行顺序以及它们如何返回任何值或异常，那么您会记得，如果`try`中引发了异常，则也将抑制`finally`块中引发的**异常**。

在 Java 7 之前的版本中，您通过记录日志了解了这些异常（如果已实现），但是一旦`finally`块结束，您就无法控制这些类型的异常。

好吧，借助 Java 7 中的[**新特性**](https://howtodoinjava.com/java7/java-7-changes-features-and-enhancements/ "java 7 features")，您还可以控制这些受抑制的异常。

```java
Table of contents

1\. What are suppressed exceptions?
2\. Suppressed exception example
3\. Demonstration in different scenarios
```

## 1\. 什么是禁止的异常？

在 Java 7 中，遇到抑制异常的最常见用例是 **try-with-resources** 语句。 当我们在`try`块中遇到异常时，应用程序将尝试关闭资源。 如果它遇到关闭`AutoCloseable`资源时可能发生的多个异常，则会将其他异常作为**抑制的异常**附加到主要异常上。

为了支持抑制的异常，在 JDK 7 中向[`Throwable`](https://docs.oracle.com/javase/7/docs/api/java/lang/Throwable.html "Throwable")类（`Exception`和`Error`类的父级）添加了新的构造器和两个新方法。

```java
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`），无论我们尝试访问它还是关闭它，它都会引发异常。 这样，当以不同方式访问时，我们将能够看到不同的行为。

```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
	 * */
	@Override
	public void close() throws Exception
	{
		throw new NullPointerException("Remember me. I am your worst nightmare !! I am Null pointer exception !!");
	}
}

```

#### 3.1 抑制异常之前的特性

```java
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 中抑制异常之后

```java
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 exception
					throw 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`块并捕获异常

```java
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`块

```java
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)

```

好吧，非常高兴看到包含**抑制异常**的完整信息的输出。

学习愉快！