在 finally 块中处理

Dealing with in a finally block

我有一些代码可以创建 JarFileURLClassLoader,我想在最后关闭它们。自然地,我决定使用 finally 块来处理清理:

JarFile jar = ...;
URLClassLoader loader = ...;
try {
    // work ...
} finally {
    jar.close();
    loader.close();
}

然而,两个 close() 调用都可以抛出异常,因此如果 jar.close() 会抛出异常,那么 loader.close() 将无法到达。我考虑解决这个问题的一种方法是用 try-catch 块包围 jar.close()

JarFile jar = ...;
URLClassLoader loader = ...;
try {
    // work ...
} finally {
    try {
        jar.close();
    } catch(IOException e) {
    } 
    loader.close();
}

但这看起来很丑陋和过分。有没有一种优雅的方法来处理 finally 块中与清理相关的异常?

在 Java 7 及更高版本中,尝试使用处理 Closeable 对象的资源。

因此重新格式化您的代码,

try(JarFile jar = ....; URLClassLoader loader = ....;) 
{
    // work ...
}

只有实现 Closeable 接口的 类 才能以这种方式工作,这两个 类 都满足此条件。

当然有办法封装这个,叫做方法!例如,您可以创建一个 class IOUtils,如下所示:

public class IOUtils {
    // this class is not meant to be instantiated
    private IOUtils() { }

    public static void closeQuietly(Closeable c) {      
       if (c == null) return;
       try {
          c.close();
       } catch (IOException e) { }
    }
}

然后,

JarFile jar = ...;
URLClassLoader loader = ...;
try {
    // work ...
} finally {
    closeQuietly(jar);
    loader.close();
}

正如 Patrick J Abae II 所说,您也可以对资源使用 try-catch,但您不能总是这样做,例如,如果您先创建一个InputStream 在 try-catch 中,然后通过封装第一个创建几种不同类型的 InputStream(例如:封装在 CipherInputStream 中以解密数据,然后写入 FileOutputStream).然而,我并不是说带有资源的 try-catch 不是一个有用的结构,它在大多数情况下就足够了。

使用try-with-resources:

    try (JarFile jar = new JarFile(filename);
            URLClassLoader loader = URLClassLoader.newInstance(urls)) {
        // do stuff
    } catch (IOException ex) {
        // handle ex           
    }