52

Please correct me if this is wrong: In Java 7's try-with-resources statement, any exceptions thrown by the resource's close() method must be either declared as thrown by my method or I must wrap the whole try in another try which catches any exceptions thrown by close().

If so, I have to wonder if I will make much use of it. I certainly don't want to throw the exceptions thrown by close(), the caller won't know what to do with that. And a try wrapping another try just to handle close() would not look very elegant, to me at least.

EDIT: I think I accidentally asked two questions, one of which was a duplicate.

Question 1. Do I have to declare that my method throws the exception from the close() method or wrap the try-with-resources in another try? (Not answered in proposed duplicate.)

Question 2. Is there a way to close the resource silently? (Clearly a duplicate, so I am taking that sentence out of the question. Hopefully this makes the question satisfactorily unique.)

John Fitzpatrick
  • 4,207
  • 7
  • 48
  • 71

4 Answers4

43

Quote from Java Language Specification ($14.20.3.2):

14.20.3.2 Extended try-with-resources

A try-with-resources statement with at least one catch clause and/or a finally clause is called an extended try-with-resources statement. The meaning of an extended try-with-resources statement:

    try ResourceSpecification
        Block
    Catchesopt
    Finallyopt

is given by the following translation to a basic try-with-resources statement (§14.20.3.1) nested inside a try-catch or try-finally or try-catch-finally statement:

    try {
        try ResourceSpecification
            Block
    }
    Catchesopt
    Finallyopt

The effect of the translation is to put the ResourceSpecification "inside" the try statement. This allows a catch clause of an extended try-with-resources statement to catch an exception due to the automatic initialization or closing of any resource.

So, basically, wrapper is already implemented

default locale
  • 13,035
  • 13
  • 56
  • 62
29

From the Java tutorial

A try-with-resources statement can have catch and finally blocks just like an ordinary try statement. In a try-with-resources statement, any catch or finally block is run after the resources declared have been closed.

(emphasis mine)

So you can simply do

try (BufferedReader br =
               new BufferedReader(new FileReader(path))) {
    return br.readLine();
}
catch (IOException e) {
    // handle the exception that has been thrown by readLine() OR by close().
}
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • 3
    That approach does not solve the problem. For me the "normal" behaviour is: 1) rethrow the exception from readLine 2) Ignore the exception thrown by close. Doing it the way you propose, there is not an easy way to know if the exception is from readLine or from close. – Rober2D2 Apr 14 '19 at 11:22
  • @Rober2D2 note `IOException` has more specific subclasses (see https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html). It may be you'll get different ones from `readline` compared to `close`. You'd have to test it out to be sure. I would like the documentation to say specifically *which* exceptions can be expected, and not just use the more general IOException. – Concrete Gannet Jul 11 '23 at 07:10
7

You do not need to wrap the try-with-resources in another try-catch block, you simply add a catch block:

class Foo implements AutoCloseable {
    public void close() throws Exception {
        throw new Exception();
    }
}

public class Try {
    public static void main(final String[] args) {
        try(Foo f = new Foo()) {
            System.out.println("No op!");
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}
Perception
  • 79,279
  • 19
  • 185
  • 195
2

You should be able to simply add the appropriate catch (Exception e) { } clause. If you need to do special handling for a specific one, or you can simply catch Exception, if you need it much broader.

try (Statement stmt = con.createStatement()) {
    ResultSet rs = stmt.executeQuery(query);

    while (rs.next()) {
        String coffeeName = rs.getString("COF_NAME");
        int supplierID = rs.getInt("SUP_ID");
        float price = rs.getFloat("PRICE");

        System.out.println(coffeeName + ", " + supplierID + ", " + 
                           price + ", " + sales + ", " + total);
    }
} catch (Exception e) {
    System.out.println("Exception while trying to through the queries. ", e);
}

Since it's Java 7, you can actually put multiple exceptions per catch clause, or you can simply catch the outermost exception you want.

mjuarez
  • 16,372
  • 11
  • 56
  • 73