Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bad practice in JDK's try-with-resources example? [duplicate]

I found this example in the try-with-resources documentation for Java:

static String readFirstLineFromFile(String path) throws IOException {
    try (BufferedReader br = new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}

If the constructor for BufferedReader throws an exception, then the resources held by the FileReader won't be released. So isn't this a bad practice to write it like that instead of:

static String readFirstLineFromFile(String path) throws IOException {
    try (FileReader fr = new FileReader(path);
         BufferedReader br = new BufferedReader(fr)) {
        return br.readLine();
    }
}
like image 897
Daniel Avatar asked Nov 02 '17 20:11

Daniel


People also ask

Can you explain about try with resources?

The try -with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try -with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.

Can we write try with resources without catch and finally?

Yes, It is possible to have a try block without a catch block by using a final block. As we know, a final block will always execute even there is an exception occurred in a try block, except System. exit() it will execute always.

Does try with resources check for NULL?

try-with-resources: A resource is closed only if it initialized to a non-null value. This can actually be useful, when a resource might present sometimes, and absent others.

Does try with resources automatically close?

The Java try with resources construct, AKA Java try-with-resources, is an exception handling mechanism that can automatically close resources like a Java InputStream or a JDBC Connection when you are done with them. To do so, you must open and use the resource within a Java try-with-resources block.


1 Answers

Indeed, just gave it a quick try:

public class MyFileReader extends FileReader {

    public MyFileReader(String fileName) throws FileNotFoundException {
        super(fileName);
    }

    @Override
    public void close() throws IOException {
        System.out.println("Closing MyFileReader");
        super.close();
    }

}

public class MyBufferedReader extends BufferedReader {

    public MyBufferedReader(Reader in) {
        super(in);
        throw new RuntimeException();
    }

    @Override
    public void close() throws IOException {
        System.out.println("Closing MyBufferedReader");
        super.close();
    }

}

public String test(String path) throws IOException {
    try (BufferedReader br = new MyBufferedReader(new MyFileReader(path))) {
        return br.readLine();
    }
}

None of MyFileReader nor MyBufferedReader is closed... Good catch!

While with:

public String test(String path) throws IOException {
    try (FileReader fr = new MyFileReader(path); BufferedReader br = new MyBufferedReader(fr)) {
        return br.readLine();
    }
}

MyFileReader is closed.

BufferedReader constructor can indeed throw exceptions, see BufferedReader(Reader in, int sz) constructor (although not when coming from BufferedReader(Reader in) constructor, but the doc you linked should still alert on this possible issue IMHO).

Looks like you won the right to raise an issue :)

like image 62
sp00m Avatar answered Oct 21 '22 12:10

sp00m