注释(用户SOC上的)回答到关于尾调用优化的问题提到了Java 7中有一个称呼,是因为“加ARM的”的“抑制异常”,新的功能(适用于ARM CPU的支持?)。
在这种情况下,什么是“受抑制的例外”?在其他情况下,“被抑制的异常”将是被捕获然后被忽略的异常(这是一个好主意)。这显然是不同的。
注释(用户SOC上的)回答到关于尾调用优化的问题提到了Java 7中有一个称呼,是因为“加ARM的”的“抑制异常”,新的功能(适用于ARM CPU的支持?)。
在这种情况下,什么是“受抑制的例外”?在其他情况下,“被抑制的异常”将是被捕获然后被忽略的异常(这是一个好主意)。这显然是不同的。
Answers:
我认为注释者所指的是一个异常,当它finally
从try-with-resources块的隐式块中抛出时,在从该try
块中抛出现有异常的情况下,它会被半忽略:
可以从与try-with-resources语句关联的代码块中引发异常。在示例writeToFileZipFileContents中,当尝试关闭ZipFile和BufferedWriter对象时,可以从try块引发一个异常,而try-with-resources语句最多可以引发两个异常。如果从try块引发异常,并且从try-with-resources语句引发一个或多个异常,则将抑制try-with-resources语句引发的那些异常,并且由该块引发的异常是一个是由writeToFileZipFileContents方法抛出的。您可以通过从try块引发的异常中调用Throwable.getSuppressed方法来检索这些受抑制的异常。
(这是引用链接页面中名为“抑制的异常”的部分。)
finally
块也抛出异常时一个块也抛出了异常try
,则来自try
区块丢失或“被抑制”(有关更多信息,请参见http://accu.org/index.php/journals/236)。Java 7刚刚添加了一种方便的方法来存储finally
块中的异常,因为异常finally
是由try-with-resources隐式生成的。
为了弄清Jon答案中的引用,方法(每次执行)只能抛出一个异常,但是在a的情况下,有try-with-resources
可能抛出多个异常。例如,可能会在块中抛出一个,而可能会从所finally
提供的隐式中抛出另一个try-with-resources
。
编译器必须确定要“真正”抛出这些错误。它选择抛出在显式代码(该try
块中的代码)中引发的异常,而不是隐式代码(该finally
块)中引发的异常。因此,隐式块中引发的异常被抑制(忽略)。这仅在多个异常的情况下发生。
try
...finally
子句close()
:stackoverflow.com/questions/3305405/…–
Exception(Exception cause)
构造函数用于将引起异常的异常包装在另一个更具描述性的异常中。但是,在这种情况下,我们正在谈论没有因果关系的两个不同的例外。异常A不会导致异常B,因此将一个包装在另一个包装中是没有意义的。另外,您假设编码器显式抛出第二个异常并可以访问第一个异常。如果两者都被库调用抛出,则不是这种情况。
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
在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异常一起添加为抑制的异常。
汇编下面的代码:
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
抑制异常是一个尝试,以资源的语句(内发生的其他例外在Java 7中引入的),当AutoCloseable
资源被关闭。由于关闭AutoCloseable
资源时可能会发生多个异常,因此会将其他异常作为抑制的异常附加到主异常中。
查看一段try-with-resources示例代码的字节码,使用标准JVM异常处理程序来容纳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()
函数[infinally块]抛出异常,则后者将被赋予更高的优先级,并被抛回到调用函数中。在这种情况下Exception thrown by the readLine() method is ignored/suppressed
。您可以将导致异常的异常链接到异常中,然后从finally块重新抛出异常。
由于java 7
已经提供了检索抑制的异常的功能。您可以public final java.lang.Throwable[] getSuppressed()
在捕获的可抛出对象上调用function来查看抑制的Exception。
例如
static String readFirstLineFromFileWithFinallyBlock(String path)
throws Exception {
try (BufferedReader br = new BufferedReader(new FileReader(path));) {
return br.readLine();
}
}
现在,如果在关闭资源时抛出了br.readLine();
线路Exception1
然后说了话Exception2
[想像这种情况发生在try-with-resource语句创建的隐式finally块中],则Exception1将抑制Exception2。
这里要注意的几点-
我在下面的文章中使用代码段和输出来编译了大多数可能的情况。
希望能有所帮助。
Exception
不会自动抑制源自try {}块的。程序员可能会选择这样做,而您没有这样做。只有在需要的情况下,try-with-resources才会自动抑制异常。而当他这样做时,您的同等的finally块中的例外将被抑制。
我认为这与“链接异常设施”有关。随着堆栈跟踪的发展,它将影响此工具如何处理异常。随着时间的流逝,可以抑制属于一组链接异常的异常。看看该Throwable的文档获取更多细节。