开发者

Is this a safe way to release resources in Java?

开发者 https://www.devze.com 2022-12-27 21:56 出处:网络
Usually when code needs some resource that needs to be released I see it done like this: InputStream in = null;

Usually when code needs some resource that needs to be released I see it done like this:

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

What I don't like is that you have to initialize the variable to null and after that set it to another value and in the finally block check if the resource was initialized by checking if it is null. If it is not null, it needs to be released. I know I'm nitpicking, but I feel like this could be done cleaner.

What I would like to do is this:

InputStream in = new FileInputStream("m开发者_如何学运维yfile.txt");
try{
    doSomethingWithStream(in);
}finally{
    in.close();
}

To my eyes this looks almost as safe as the previous one. If resource initialization fails and it throws an exception, there's nothing to be done(since I didn't get the resource) so it doesn't have to be inside the try block. The only thing I'm worried is if there is some way(I'm not Java certified) that an exception or error can be thrown between operations?

Even simpler example:

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

Is there any way the stream would be left open that a try-finally block would prevent?

Edit:

Maybe I should have left out the last example because it confuses everyone. This is not supposed to be a beginner level question. I know what try-finally does and I know that it is not safe if there was doSomethingWithStream in the middle in the last example. That is why it is not there. I accepted Eyals answer because it was precisely what I was looking for. There is a way to cause an exception between two operations, which would make the middle example unsafe(using Thread.stop), but since it is made using deprecated call and can mess you up no matter what you do so I feel safe using the middle example.


The middle sample is safe - the last one isn't.

A try-finally block means that the stream is closed even if doSomethingWithStream throws an exception. Yes, you could catch all exceptions and then close the stream that way - but it's much simpler to let the exception bubble up to the caller, but close the stream on the way via the finally block.


Actually, an exception can occur between the 2 calls in the last code sample,and leave the resource open. If the thread is stopped violently by another thread using the Thread.stop() or Thread.stop(Throwable) immediately after the stream construction, the thread will throw an exception (ThreadDeath in the first case), and the resources will not be disposed of.

But this is exactly why these methods are deprecated...


Look into Project Lombok. It has a @Cleanup annotation which is settable on local variables which will auto-generate code at compilation time to clean up the resource.

 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);
     }
   }
 }
0

精彩评论

暂无评论...
验证码 换一张
取 消