我想知道,当异常发生时,try with resource语句如何在进入catch块之前关闭资源。当异常发生时,执行立即跳转到catch块。因此,try-with-resource实际上关闭了资源。
为了更好地理解它的工作原理,我决定看看编译器是如何实现它的。我编写了下面的代码并对其进行了编译。
public class Test
{
public static void main(final String[] args) {
//I used same JDK for compilation and execution.
System.out.println("Java version: " + System.getProperty("java.version") + "\n");
try(CloseMe me = new CloseMe();
CloseMeToo meToo = new CloseMeToo()){
System.out.println("trying");
throw new Exception("try failed");
} catch(Exception e) {
System.out.println("failed");
System.out.println("\n");
System.out.println(e.getMessage());
System.out.println(e.getSuppressed()[0].getMessage());
System.out.println(e.getSuppressed()[1].getMessage());
}
}
}
class CloseMe implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println("me closing!");
throw new Exception("don't close me :o");
}
}
class CloseMeToo implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println("meToo closing!");
throw new Exception("don't close me too :O");
}
}
输出
Java version: 15.0.1
trying
meToo closing!
me closing!
failed
try failed
don't close me too :O
don't close me :o
然后我访问了www.javadecompilers.com,并在那里试用了反编译程序。两个反编译程序给出了不错的结果:CFR0.150和Fernflower。CFR是最可读性和完整的,所以张贴在这里。
public class Test
{
public static void main(final String[] args) throws Throwable{
System.out.println("Java version: " + System.getProperty("java.version") + "\n");
try {
Throwable throwable = null;
Object var2_4 = null; //<-- where this variable is used?
try {
CloseMe me = new CloseMe();
try {
CloseMeToo meToo = new CloseMeToo();
try {
System.out.println("trying");
throw new Exception("try failed");
}
catch (Throwable throwable2) {
throwable = throwable2; //<-- I put this line to make it work
if (meToo != null) {
meToo.close();
}
throw throwable2;
}
}
catch (Throwable throwable3) {
if (throwable == null) {
throwable = throwable3;
} else if (throwable != throwable3) {
throwable.addSuppressed(throwable3);
}
if (me != null) {
me.close();
}
throw throwable;
}
}
catch (Throwable throwable4) {
if (throwable == null) {
throwable = throwable4;
} else if (throwable != throwable4) {
throwable.addSuppressed(throwable4);
}
throw throwable;
}
}
catch (Exception e) {
System.out.println("failed");
System.out.println("\n");
System.out.println(e.getMessage());
System.out.println(e.getSuppressed()[0].getMessage());
System.out.println(e.getSuppressed()[1].getMessage());
}
}
}
我知道反编译器有局限性。理想的反编译器会给我同样的尝试资源,我不会看到这些细节。所以可以。
我的问题是:
var2_4
未使用。此外,我还必须添加一行以使其像try-with-resource一样工作。我认为代码不完整。如果有,你能补充/解释缺少的部分吗?谢谢!
在Java语言规范第14.20.3节中充分记录了使用资源进行尝试的行为。尝试使用资源。
具体表现为以下缩写版的问题代码:
try (CloseMe me = new CloseMe(); CloseMeToo meToo = new CloseMeToo()) {
System.out.println("trying");
} catch (Exception e) {
System.out.println("failed");
}
首先转换为:
try {
try (CloseMe me = new CloseMe(); CloseMeToo meToo = new CloseMeToo()) {
System.out.println("trying");
}
} catch (Exception e) {
System.out.println("failed");
}
然后向:
try {
final CloseMe me = new CloseMe();
Throwable #primaryExc1 = null;
try (CloseMeToo meToo = new CloseMeToo()) {
System.out.println("trying");
} catch (Throwable #t) {
#primaryExc1 = #t;
throw #t;
} finally {
if (me != null) {
if (#primaryExc1 != null) {
try {
me.close();
} catch (Throwable #suppressedExc) {
#primaryExc1.addSuppressed(#suppressedExc);
}
} else {
me.close();
}
}
}
} catch (Exception e) {
System.out.println("failed");
}
然后向:
try {
final CloseMe me = new CloseMe();
Throwable #primaryExc1 = null;
try {
final CloseMeToo meToo = new CloseMeToo()
Throwable #primaryExc2 = null;
try {
System.out.println("trying");
catch (Throwable #t) {
#primaryExc2 = #t;
throw #t;
} finally {
if (meToo != null) {
if (#primaryExc2 != null) {
try {
meToo.close();
} catch (Throwable #suppressedExc) {
#primaryExc2.addSuppressed(#suppressedExc);
}
} else {
meToo.close();
}
}
}
} catch (Throwable #t) {
#primaryExc1 = #t;
throw #t;
} finally {
if (me != null) {
if (#primaryExc1 != null) {
try {
me.close();
} catch (Throwable #suppressedExc) {
#primaryExc1.addSuppressed(#suppressedExc);
}
} else {
me.close();
}
}
}
} catch (Exception e) {
System.out.println("failed");
}
我的系统中有以下配置: Apache Maven 3.5.2 Maven主页: /usr/share/mavenJava版本:1.8.0_162,供应商:Oracle CorporationJava主页: /usr/lib/jvm/java-8-openjdk-amd64/jre默认语言环境:en_US,平台编码:UTF-8操作系统名称:"linux",版本:"4.15.0-20-通用", arc
我需要打开N个多播套接字(其中N来自参数列表的大小)。然后,我将向循环中的N个套接字中的每个套接字发送相同的数据,最后关闭每个套接字。我的问题是,如何使用try with resources块来实现这一点?以下是我将如何使用单个资源来实现这一点: 我能想到的使用多个端口执行此操作的唯一方法如下: 有没有一种更简洁的方法来实现这一点,或者我提出的解决方案是否尽可能好?
问题内容: 我正在为Pascal的子集编写编译器。编译器为一台组装好的机器生成机器指令。我想为此机器语言编写一个窥孔优化器,但是我无法替换一些更复杂的模式。 窥孔优化器规格 我研究了几种编写窥孔优化器的方法,并且选择了后端方法: 每当要生成机器指令时,编码器都会调用函数。 检查猫眼优化表: 如果当前指令与模式的尾部匹配: 检查先前发出的说明是否匹配 如果所有指令都与该模式匹配,则应用优化,修改代码
问题内容: 我一直在看代码,并且看到了尝试资源的机会。我以前使用过标准的try-catch语句,看起来它们在做同样的事情。所以我的问题是“ 尝试使用资源”与“尝试捕获 ”之间的区别是什么,哪个更好。 这是尝试使用资源: 问题答案: 尝试使用资源的重点是确保可靠地关闭资源。 当你不使用try-with-resources时,存在一个潜在的陷阱,称为异常屏蔽。当try块中的代码引发异常,而finall
无法从com提取资源。AndroidAAPT编译器。ParsedResource@636e1e76. 任务“:app:mergeDebugResources”的执行失败。 执行com.android.build.gradle.internal.res.时发生故障ResourceCompilerRunnable资源编译失败(未能编译值资源文件E:\My Client\Henkako\HenkakoP
问题内容: 我是的新手,我想知道对于资源来说,我是否必须为每个添加一个,否则它将与上面的代码一起使用 问题答案: 通过在 块中声明所有资源,可以尝试将资源与多个资源一起使用,并且此功能是 Java 7中 引入的,而不是 Java 8中 引入的。如果有多个资源,则可以如下所示 在此示例中,该语句包含两个用分号分隔的声明: ZipFile 和 BufferedWriter 。当它紧随其后的代码块终止时