使用 try-with-resources 关闭一个 Closeable

use try-with-resources to close a Closeable

我有一个 Map<Key, Closeable>,如果从地图上删除了一个键,我想关闭 Closeable。通常我有这样的东西:

Closeable c = map.remove(key);
c.close();

我的 Eclipse 警告我 "Resource 'c' should be managed by try-with-resource",所以只写以下内容会更好吗?

try (Closeable c = map.remove(key)) {}

在我的特殊实现中,我有一个 Closeable 的子类,其中 close() 不会抛出 IOException,因此不需要异常处理。

我会忽略这个警告,如果您自己管理关闭操作,那么只需调用 close()。空的 try-with-resource 看起来很奇怪。

考虑扩展 Map,以便在移除时自动执行关闭操作:

public class CloseableMap<K,V extends Closeable> extends HashMap<K,V> {

    @Override
    public R remove(K key) {
        V resource = super.remove(key);
        if (resource != null) {
            resource.close();
        }
        return resource;
    }
}

try-with-resources 的要点在于:

  • Closeable资源的打开是在try语句中完成的
  • 资源的使用在 try 语句块内
  • close()自动为您呼叫。

所以你建议的代码:

try(Closeable c = map.remove(key)) {}

... 不满足 try-with-resource 的要求,因为您没有使用块内的资源。据推测,您的 Closeable 在此声明之前已经打开。

我猜你有一些代码可以打开一堆资源,完成工作,然后通过地图工作将它们全部关闭。

这没关系,有时也是不可避免的。但在可能的情况下,在同一方法中使用 open()close() 更简洁,在 finally 块中使用 close(),这样您就可以一目了然每个 open() 都有对应的 close() 并且您可以确定 close() 总是被调用。

MyCloseable c = MyCloseable.open(...);
try{
       // do stuff with c;
} finally {
     try {
         c.close();
     } catch (IOException e) {
         // ...
     }
}

一旦你做到了这一点,try-with-resources 只会让事情变得更整洁:

try(MyCloseable c = MyCloseable.open(...)) {
    // do stuff with c;
}

如果您的要求意味着您无法打开和关闭相同的方法,那么只需坚持使用明确的 close() 并忽略警告。