提问人:Raedwald 提问时间:10/21/2011 最后编辑:CommunityRaedwald 更新时间:1/20/2022 访问量:70803
什么是禁止显示的异常?
What is a suppressed exception?
问:
在回答有关尾部调用优化的问题时,用户 soc 的评论提到 Java 7 有一个称为“抑制异常”的新功能,因为“添加了 ARM”(支持 ARM CPU?
在这种情况下,什么是“禁止显示的异常”?在其他情况下,“抑制的异常”将是捕获然后忽略的异常(很少是一个好主意);这显然是不同的东西。
答:
我相信评论者所指的是一个异常,当它被抛出在try-with-resources块的隐式块中时,在从该块抛出现有异常的上下文中时,该异常被半忽略:finally
try
可以从与 try-with-resources 语句关联的代码块引发异常。在示例 writeToFileZipFileContents 中,可以从 try 块引发异常,并且当 try-with-resources 语句尝试关闭 ZipFile 和 BufferedWriter 对象时,最多可以从该语句引发两个异常。如果从 try 块引发异常,并且从 try-with-resources 语句引发一个或多个异常,则禁止从 try-with-resources 语句引发的这些异常,并且该块引发的异常是 writeToFileZipFileContents 方法引发的异常。可以通过从 try 块引发的异常中调用 Throwable.getSuppressed 方法来检索这些抑制的异常。
(这是引用链接页面中名为“抑制的异常”的部分。
评论
finally
try
try
finally
finally
为了澄清 Jon 回答中的引述,一个方法(每次执行)只能抛出一个异常,但在 的情况下,可能会抛出多个异常。例如,一个可能被抛出到块中,另一个可能被抛出。try-with-resources
finally
try-with-resources
编译器必须确定要“真正”抛出其中的哪一个。它选择抛出显式代码(块中的代码)中引发的异常,而不是隐式代码(块)引发的异常。因此,隐式块中抛出的异常将被禁止(忽略)。这仅在出现多个异常的情况下发生。try
finally
评论
try
finally
close()
Exception(Exception cause)
If an exception is thrown from the try block and one or more exceptions are thrown from the try-with-resources statement, then those exceptions thrown from the try-with-resources statement are suppressed
禁止的异常是关闭 AutoCloseable
资源时,try-with-resources 语句(在 Java 7 中引入)中发生的其他异常。由于在关闭资源时可能会发生多个异常,因此其他异常将作为禁止的异常附加到主异常。AutoCloseable
查看一段 try-with-resources 示例代码的字节码,使用标准 JVM 异常处理程序来适应 try-with-resources 语义。
我认为这与“链式异常设施”有关。随着堆栈跟踪的发展,它将影响此工具处理异常的方式。随着时间推移,属于一组链式异常的异常可能会被抑制。有关更多详细信息,请查看 Throwable 文档。
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();
}
}
现在,如果函数抛出异常,然后甚至函数 [in finally block] 抛出异常,那么后者被赋予更多优先级并被抛回调用函数。在本例中,.您可以在异常中链接导致异常,并从 finally 块重新抛出异常。readLine()
close()
Exception thrown by the readLine() method is ignored/suppressed
由于提供了检索抑制异常的功能。您可以对捕获的可抛出对象调用函数来查看抑制的异常。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();
}
}
现在,如果抛出行,然后假设在关闭资源时抛出 [想象一下这发生在 try-with-resource 语句创建的隐式 finally 块中],则 Exception1 会抑制 Exception2。br.readLine();
Exception1
Exception2
这里需要注意的几点——
- 如果 try-with-resource 块抛出异常,即在资源实例化时,则 try 块将不会执行,并且会抛出相同的异常。
- 如果资源实例化成功,则 try 块会引发异常,并且在关闭资源时会引发异常,然后关闭资源时引发的异常会被 try 块抛出的异常抑制。
- 如果提供显式 finally 块,并且从该块抛出异常,它将禁止所有其他异常。(此显式 finally 块在资源关闭后执行)
在下面的帖子中,我已经用代码片段和输出编译了大多数可能的场景。
希望能有所帮助。
评论
Exception
您也可以在 Java 6 中抑制异常(涉及一些诡计),
我创建了一个实用程序,可以透明地处理 Java 1.6 和 Java 1.7 中的抑制异常。您可以在此处找到实现
您只需要致电:
public static <T extends Throwable> T suppress(final T t, final Throwable suppressed)
以抑制异常,以及
public static Throwable [] getSuppressed(final Throwable t) {
获取 Exception 的抑制异常,以防有人仍在使用 Java 1.6
在 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 {
}
在 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 中引入,旨在使轻松跟踪异常之间的因果关系成为可能。
承认以下代码:
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
评论