use*_*412 3 java exception-handling
我试图理解 Java SE7 中的抑制异常,我在下面发布了 2 个示例,它们是相似的,在下面的示例中,我的印象是,当新的“主异常”发生时,被抑制的异常会被忽略,例如我是期望输出为“java.lang.RuntimeException: y”,但答案是:
java.lang.RuntimeException: y
suppressed java.lang.RuntimeException: a
这是代码:
class Animal implements AutoCloseable{
@Override
public void close() {
throw new RuntimeException("a");
}
}
public class ExceptionsDemo {
public static void main(String[] args) throws IOException {
try(Animal a1 = new Animal();){
foo();
}
catch(Exception e){
System.err.println(e);
for(Throwable t : e.getSuppressed()){
System.err.println("suppressed "+ t);
}
}
}
static void foo() {
try {
throw new RuntimeException("x");
} catch (Exception e) {
throw new RuntimeException("y");
}
}
}
Run Code Online (Sandbox Code Playgroud)
我的理解是,在 tryWithResources 子句之后,“a”是主 Exc,然后在 foo() 中,x 成为主 exc 而 a 被抑制,但在 catch 中,我认为 y 将成为单独的主 exc 并将忽略所有其他异常,包括压制的?
像第二个例子,它做我刚才提到的,它输出 java.lang.RuntimeException: c 没有抑制异常。
public class ExceptionDemo2 {
class Animal implements AutoCloseable{
@Override
public void close() {
throw new RuntimeException("a");
}
}
public static void main(String[] args) {
try{
new ExceptionDemo2().go();
}
catch(Exception e){
System.err.println(e);
for(Throwable t : e.getSuppressed()){
System.err.println("suppressed "+ t);
}
}
}
void go(){
try(Animal a = new Animal()){
throw new IOException();
}catch(Exception e){
throw new RuntimeException("c");
}
}
}
Run Code Online (Sandbox Code Playgroud)
输出: java.lang.RuntimeException: c
你的榜样
try(Animal a1 = new Animal();){
foo();
}
catch(Exception e){
System.err.println(e);
for(Throwable t : e.getSuppressed()){
System.err.println("suppressed "+ t);
}
}
Run Code Online (Sandbox Code Playgroud)
因为foo()抛出一个RuntimeException( y) 而终止。这就是catch. 因为执行离开try块,所有声明的资源都被关闭。关闭Animal实例时,会抛出另一个RuntimeException( a)。那个被压制了,因为它不是根本原因。
try-with-resources到try-catch-finally块的翻译在 JLS 中解释,这里。
基本 try-with-resources 语句的含义:
Run Code Online (Sandbox Code Playgroud)try ({VariableModifier} R Identifier = Expression ...) Block由以下转换为局部变量声明和 try-catch-finally 语句给出:
Run Code Online (Sandbox Code Playgroud){ final {VariableModifierNoFinal} R Identifier = Expression; Throwable #primaryExc = null; try ResourceSpecification_tail Block catch (Throwable #t) { #primaryExc = #t; throw #t; } finally { if (Identifier != null) { if (#primaryExc != null) { try { Identifier.close(); } catch (Throwable #suppressedExc) { #primaryExc.addSuppressed(#suppressedExc); } } else { Identifier.close(); } } } }
在哪里
如果资源规范声明了一个资源,
ResourceSpecification_tail则为空(并且 try-catch-finally 语句本身不是 try-with-resources 语句)。
你上面的代码基本上转化为类似的东西
try {
final Animal a1 = new Animal();
Throwable thr = null;
try {
foo();
} catch (Throwable root) {
thr = root;
throw root;
} finally {
if (a1 != null) {
if (thr != null) {
try {
a1.close();
} catch (Throwable suppressed) {
thr.addSuppressed(suppressed); // <<<<<< suppressing the failure of 'close'
}
} else {
a1.close();
}
}
}
} catch (Exception e) {
System.err.println(e);
for (Throwable t : e.getSuppressed()) {
System.err.println("suppressed " + t);
}
}
Run Code Online (Sandbox Code Playgroud)