Java 抑制异常的示例

培训教学 潘老师 8个月前 (09-18) 157 ℃ (0) 扫码查看

顾名思义,抑制异常是在代码中抛出但以某种方式被忽略的异常。如果您还记得try-catch-finally块的执行顺序以及它们如何返回任何值或异常,您会记得在try块中抛出异常的同时,如果在finally块中抛出异常,那么finally块中抛出的异常会被抑制。

在Java 7之前,如果实现了日志记录,您会通过日志记录来了解这些异常,但一旦finally块结束,您就无法控制这些类型的异常。

好吧,借助Java 7 中的新功能,您还可以控制这些被抑制的异常。

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

3.1. 抑制异常功能之前

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 中抑制异常支持之后

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 块并捕获异常

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 块

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)

嗯,看到包含完整信息和抑制异常的输出真是太棒了。


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/teach/9114.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】