这是一种在Java中释放资源的安全方法吗?

时间:2010-04-25 12:41:44

标签: java

通常当代码需要一些需要释放的资源时,我看到它是这样做的:

InputStream in = null;
try{
    in = new FileInputStream("myfile.txt");
    doSomethingWithStream(in);
}finally{
    if(in != null){
        in.close();
    }
}

我不喜欢的是你必须将变量初始化为null,然后将其设置为另一个值,并在finally块中检查资源是否通过检查是否为null来初始化。如果它不为null,则需要释放它。我知道我在挑剔,但我觉得这可以做得更干净。

我想做的是:

InputStream in = new FileInputStream("myfile.txt");
try{
    doSomethingWithStream(in);
}finally{
    in.close();
}

在我看来,这看起来几乎和前一个一样安全。如果资源初始化失败并且它抛出异常,则没有什么可做的(因为我没有得到资源)所以它不必在try块内。我唯一担心的是,如果有某种方式(我不是Java认证)可以在操作之间抛出异常或错误吗?

更简单的例子:

Inputstream in = new FileInputStream("myfile.txt");
in.close();

有没有什么方法可以让一个try-finally块阻止的流被打开?

修改

也许我应该省略最后一个例子,因为它让每个人都感到困惑。这不应该是一个初学者级别的问题。我知道try-finally做了什么,我知道如果在最后一个例子中间有doSomethingWithStream则不安全。这就是它不存在的原因。我接受了Eyals的回答,因为这正是我所寻找的。有一种方法可以在两个操作之间导致异常,这会使中间示例不安全(使用Thread.stop),但由于它是使用不推荐的调用制作的,并且无论你做什么都会弄乱你,所以我觉得安全使用中间的例子。

3 个答案:

答案 0 :(得分:2)

中间样本是安全的 - 最后一个样本不是。

try-finally块意味着即使doSomethingWithStream抛出异常,流也会关闭。是的,您可以捕获所有异常,然后以这种方式关闭流 - 但是让异常冒泡到调用者更简单,但是通过finally块关闭流。

答案 1 :(得分:1)

实际上,最后一个代码示例中的2个调用之间可能会发生异常,并使资源保持打开状态。如果线程在流构造之后立即使用Thread.stop()或Thread.stop(Throwable)被另一个线程猛烈地停止,则线程将抛出异常(第一种情况下为ThreadDeath),并且资源不会被处置的。

但这正是这些方法被弃用的原因......

答案 2 :(得分:0)

查看Project Lombok。它有一个@Cleanup注释,可以在局部变量上设置,auto-generate code at compilation time将清理资源。

 import lombok.Cleanup;
 import java.io.*;

 public class CleanupExample {
   public static void main(String[] args) throws IOException {
     @Cleanup InputStream in = new FileInputStream(args[0]);
     @Cleanup OutputStream out = new FileOutputStream(args[1]);
     byte[] b = new byte[10000];
     while (true) {
       int r = in.read(b);
       if (r == -1) break;
       out.write(b, 0, r);
     }
   }
 }