代码之家  ›  专栏  ›  技术社区  ›  palto

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

  •  1
  • palto  · 技术社区  · 15 年前

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

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

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

    我想做的是:

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

    在我看来,这几乎和前一个一样安全。如果资源初始化失败并引发异常,则没有任何操作要做(因为我没有得到该资源),因此它不必位于try块中。我唯一担心的是,是否有某种方式(我不是Java认证)可以在操作之间抛出异常或错误?

    更简单的例子:

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

    有没有任何方法可以让流保持打开状态,从而阻止try finally块?

    编辑:

    也许我应该忽略最后一个例子,因为它让每个人都困惑。这不应该是初级问题。我知道尝试最终会做什么,我知道如果在上一个例子中中间有剂量流,那是不安全的。这就是为什么它不在那里。我接受了艾尔斯的回答,因为这正是我想要的。有一种方法可以在两个操作之间引发异常,这会使中间示例不安全(使用thread.stop),但由于它是使用不推荐使用的调用生成的,无论您做什么,都会使您陷入困境,因此使用中间示例我感到安全。

    3 回复  |  直到 15 年前
        1
  •  1
  •   Eyal Schneider    15 年前

    实际上,在最后一个代码示例中的两个调用之间可能会发生异常,并使资源保持打开状态。如果线程在流构造后立即被另一个线程使用thread.stop()或thread.stop(可丢弃)猛烈停止,则线程将引发异常(在第一种情况下为threaddeath),并且不会释放资源。

    但这正是这些方法被否决的原因…

        2
  •  2
  •   Jon Skeet    15 年前

    中间的样品是安全的,最后的不安全。

    try finally块意味着流已关闭,即使 doSomethingWithStream 引发异常。是的,您可以捕获所有异常,然后以这种方式关闭流——但是让异常冒泡到调用方,但通过finally块在路上关闭流要简单得多。

        3
  •  0
  •   Chris Dennett    15 年前

    观察 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);
         }
       }
     }