java 解决或取消“try-with-resources”变量未使用警告

56lgkhnf  于 2023-05-15  发布在  Java
关注(0)|答案(3)|浏览(190)

在Java 17中,我有一个生成树结构的序列化器。在生成子实体之前,我增加了缩进级别;然后我降低缩进级别。通常情况下,应该在try/finally中完成,以防止串行器在出现错误时处于损坏状态:

increaseIndentLevel();
try {
  serializeChildren()
} finally {
  decreaseIndentLevel()
}

使用try-with-resources,我创建了一个聪明而优雅的小子框架,以更流畅的方式确保这一点:

protected Closeable increaseIndentLevel() {
  indentLevel++;
  return Close.by(this::decreaseIndentLevel);
}

Close.by()是我的助手类,它创建了一个Closeable,可以像上面一样降低缩进级别;我可以这样使用它:

try (final Closeable indention = increaseIndentLevel()) {
  serializeChildren()
}

不幸的是,OpenJDK javac 17打开了linting,并没有意识到我的聪明,而是抱怨道:
[警告] auto-closeable resource indention is never referenced in body of corresponding try statement
我知道try-with-resources需要声明一些变量。例如,我不能说try (increaseIndentLevel())。(我也能猜到原因:这个特性的创建者没有足够的概括,而是为明显的99%的用例创建了不必要的限制性规则。实际上,在概念上不需要在这里要求变量;如果主体需要引用某些内容,编译器足够聪明,可以注意到引用的变量不存在。
你知道怎么避开这个警告吗?
作为最后的手段,我应该在@SuppressWarnings()中使用什么标识符来消除javac中的这个警告?(我不得不压制警告,因为它把这样一个漂亮的解决方案变成了如此丑陋的东西。)

x3naxklr

x3naxklr1#

我会写这样的东西来避免易变性。如果没有看到更多的用例,很难知道该建议什么:

import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Indenter {
    private final int indentLevel;

    public Indenter(int indentLevel) {
        this.indentLevel = indentLevel;
    }

    public void withIndent(Consumer<Indenter> f) {
        f.accept(new Indenter(indentLevel + 1));
    }

    public void indent(String s) {
        // must be a neater way to do this?
        System.out.println(IntStream.range(0, indentLevel).mapToObj(i -> " ").collect(Collectors.joining()) + s);
    }

    public static void main(String[] args) {
        Indenter i = new Indenter(0);
        i.indent("x");
        i.withIndent(i2 -> {
            i2.indent("y");
        });
    }
}
x7yiwoj4

x7yiwoj42#

从@Mihe对这个问题的评论中得到提示,一个解决方案是编译器本身的disable the try linting,就像Maven中的这样:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <configuration>
    <compilerArgs>
      <!-- suppress warnings for try-with-resources in
          serializer indentation encpsulation -->
      <arg>-Xlint:all,-try</arg>
    </compilerArgs>
  </configuration>
</plugin>

我还是觉得这有点过分我考虑重构代码以使用@tgdavies的函数式方法,但我还没有做出决定。我想我提供这个解决方案是为了完整性。

goqiplq2

goqiplq23#

我最终做的是在我的Close实用程序中添加一个额外的(noop)帮助器方法。

try (final Closeable indention = increaseIndentLevel()) {
    Close.suppressUnused(indentation);

    serializeChildren()
}

另一种方法是添加到关闭收集器:

try (final CloseLine close = new CloseLine()) {
    close.with(increaseIdentation());

    serializeChildren()
}

我更喜欢第一个。两者都添加了两行,其中一行是空的。第一种在实现和可读性上都要简单得多,而且它得到了优化。

相关问题