gpt4 book ai didi

java - try-with-resources 中的死代码警告,但不是翻译的 try-catch-finally

转载 作者:搜寻专家 更新时间:2023-11-01 03:47:46 25 4
gpt4 key购买 nike

以下代码使用 try-with-resources Java 8 中引入的构造。occasionallyThrow() 方法声明为抛出 OccasionalExceptionResourceclose() 方法抛出 CloseException。 Eclipse(版本:Neon Release (4.6.0),Build id:20160613-1800)在标有//dead code的行添加了一个警告,提示该分支是dead code。隐式地,Eclipse 确认标有//alive code 的行不是死代码。

Object tryWithResources() throws OccasionalException {
Object value = null;
try (Resource resource = new Resource()) {
occasionallyThrow();
value = new Object();
}
catch (CloseException e) {
if (value == null) {
// alive code
}
else {
// dead code
}
}
return value;
}

我对此感到困惑。如果 occasionallyThrow() 抛出它的 OccasionalException,那么 try-with-resources 应该将其捕获为主要异常,然后尝试关闭资源.如果关闭资源抛出一个CloseException,那么它将被抑制在OccasionalException下,所以不会有CloseException被捕获。因此,唯一应该捕获 CloseException 的时间是 try 中的 block 成功完成,这意味着 value 不为空。所以看起来“死代码”实际上是活的,“活代码”实际上是死的。我不确定这里的编译器实际上应该识别什么,但至少,这里的“死代码”似乎应该被称为死代码。

让事情变得更复杂的是,没有使用 try-with-resources 形式的翻译形式根本不会被标记为任何死代码警告。 (基于 14.20.3.2. Extended try-with-resources ,我非常有信心我的翻译是正确的,但如果这里有错误,我不会感到完全惊讶……)

Object expandedTry() throws OccasionalException {
Object value = null;
try {
Resource resource = new Resource();
Throwable $primary = null;
try {
occasionallyThrow();
value = new Object();
}
catch (Throwable t) {
$primary = t;
throw t;
}
finally {
if (resource != null) {
if ($primary != null) {
try {
resource.close();
}
catch (Throwable $suppressed) {
$primary.addSuppressed($suppressed);
}
}
else {
resource.close();
}
}
}
}
catch (CloseException e) {
if (value == null) {
// alive (not dead!)
}
else {
// alive
}
}
return value;
}

我是否遗漏了一些东西,这些东西会使 if-else 中的任一分支在其中一个分支中死亡,但在另一个分支中却没有?

完整代码

这是包含辅助异常类型、Resource 类和顶级类定义的完整代码。

public class TestTryWithResources {

/** Exception thrown by Resource's close() method */
@SuppressWarnings("serial")
static class CloseException extends Exception {}

/** AutoCloseable declared to throw a CloseException */
static class Resource implements AutoCloseable {
@Override
public void close() throws CloseException {}
}

/** An occasionally thrown exception */
@SuppressWarnings("serial")
static class OccasionalException extends Exception {}

/** Method declared to throw an occasional exception */
void occasionallyThrow() throws OccasionalException {}

/*
* Method using try-with-resources. Eclipse warns that the
* portion marked with "// dead code" is Dead code.
*/
Object tryWithResources() throws OccasionalException {
Object value = null;
try (Resource resource = new Resource()) {
occasionallyThrow();
value = new Object();
}
catch (CloseException e) {
if (value == null) {
// alive code
}
else {
// dead code
}
}
return value;
}

/*
* Method not using try-with-resources. This is the translation
* of the try-with-resources in tryWithResources, according to
* [14.20.3 try-with-resources][1]. Eclipse does not warn about
* any of the code being Dead code.
*
* [1]: https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.3
*/
Object expandedTry() throws OccasionalException {
Object value = null;
try {
Resource resource = new Resource();
Throwable $primary = null;
try {
occasionallyThrow();
value = new Object();
}
catch (Throwable t) {
$primary = t;
throw t;
}
finally {
if (resource != null) {
if ($primary != null) {
try {
resource.close();
}
catch (Throwable $suppressed) {
$primary.addSuppressed($suppressed);
}
}
else {
resource.close();
}
}
}
}
catch (CloseException e) {
if (value == null) {
// alive
}
else {
// alive
}
}
return value;
}
}

对评论的回应

Amin J's answer建议在设置 value 后使用资源来更改 Eclipse 的代码分析。但这不起作用。使用资源后,例如通过打印它,死代码警告仍然存在于 Luna 和 Neon 中:

Luna dead code warning, in spite of using resource after assigning to value

Neon dead code warning, in spite of using resource after assigning to value

最佳答案

出于某种原因,静态代码分析器认为根据 this,资源将在 try 声明后立即关闭。 tutorial 声明后资源关闭。

try-with-resources 语句确保每个资源都在语句结束时关闭。

因此,例如,如果您更改代码以在值为 is 之后使用资源(下面的代码),它不会警告您有关死代码的信息(但是在 Eclipse Luna 上测试过)。

Object tryWithResources() throws OccasionalException {
Object value = null;
try (Resource resource = new Resource()) {
occasionallyThrow();
value = new Object();
resource.someMethod(); // using the resource, so eclipse thinks it's not closed yet (correctly)
}
catch (CloseException e) {
if (value == null) {
// alive code
}
else {
// dead code
}
}
return value;
}

更新

这是我在设置值后使用资源(在本例中为 reader)测试的实际代码。

        Object val = null;

try (BufferedReader reader = new BufferedReader(new FileReader("C:\\file.txt"))) {
val = new Object();
System.out.println("got here");
reader.readLine();
}
catch(IOException e){
System.out.println("io ex");
if ( val == null){

}
else{

}
}

关于java - try-with-resources 中的死代码警告,但不是翻译的 try-catch-finally,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39598715/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com