简体   繁体   中英

Disadvantages of Java try-with-resources

I have a method which loads a file into a reader. Tests or other code can use this reader to read the file. The problem is that I cannot declare the reader outside of the try-with-resources/TWR block. Is this a disadvantage of TWR or am I missing something ?

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class TestngTesting {
    BufferedReader fileReader;//Can't declare this as final, because its not assigned here itself.
    BufferedReader fileReader1;

    //Can be made @BeforeClass method.
    public void loadFile() throws IOException {
        fileReader = new BufferedReader(new FileReader("path/file.txt"));

        //Compile error - Variable used as a try-with-resources resource should be final or effectively final.
        try(fileReader){

        }

        try{
            fileReader1 = new BufferedReader(new FileReader("path/file.txt"));
        }finally {
            //end gracefully.
        }
    }
}

PS - I read these two posts before posting my question - link , link .

It's not.

If you want to safely work with resources, you need to define some lexical scope within which the resource is valid, and anytime code transitions outside of this scope, it is invalid.

Failure to do so means that neither the compiler nor any linting tool can track if you're doing it right, so now it's a tossup, and bugs are hard to detect. If you really want that, cool – but ARM is already right out, the point of ARM is to make it simple to do the lexical limitation thing.

If you can't find a way to use a try-with-resources block (ARM) to do it, then you don't have the lexical scope situation. However, that doesn't mean you're immediately doomed to the old unsafe-ish way.

You can have a field containing a resource without losing ARM .

But, it does mean the object with that field must itself become AutoClosable - you can shift the burden of try-with-resources scoping elsewhere, to code that calls your resource-using code. Then all you have to do, is close that resource in your own close() method, which is the only method you have to implement if you implements AutoClosable (doing that lets other code try-with-resources instances of your class).

Of course, if all you wanted was shift the declaration without a particularly sensible reason, ARM does indeed 'encode' the code style where you declare a variable only when you need it, and not the style where you declare everything at the top.

From my experience and perusing various style guides, 'declare all local vars at the top' is uncommon, and has downsides; declarations are lexically scoped. That's a good thing, and for something like ARM, crucial. After all, I don't WANT to touch that variable once it's already closed, for the vast majority of resources, doing anything with them post-close() is an immediate exception anyway.

The problem is that I cannot declare the reader outside of the try-with-resources/TWR block. Is this a disadvantage of TWR or am I missing something ?

You can always declare and initialize it in the try-with-resources block:

try(BufferedReader fileReader = new BufferedReader(new FileReader("path/file.txt"))){
      // Print each line
      String line;
      while ((line = fileReader.readLine()) != null) {
          System.out.println(line);
      }
} catch (IOException e) {
     System.err.format("IOException: %s%n", e);
}

You can re-assign it to a local variable:

public class TestngTesting {
    BufferedReader fileReader;

    public void loadFile() throws IOException {
        fileReader = new BufferedReader(new FileReader("path/file.txt"));

        try (BufferedReader r = fileReader) {

        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM