简体   繁体   中英

Why can't I access variables inside a try/catch block?

Say I have the following code:

try {
    Reader reader = new FileReader("/my/file/location");
    //Read the file and do stuff
} catch(IOException e) {
    e.printStackTrace();
} finally {
    reader.close();
}

Why does reader only exist within the scope of the try brackets? Is this to stop an Exception being thrown earlier on in the code where the object reader was yet to be initialised or set?

How should I go about cleaning up objects that exist within the try clause, or do I have to bring them outside?

You have to bring them outside, because otherwise the variable exists only within the try block. But this is an improvement. If you change your code to this:

Reader reader = new FileReader("/my/file/location");
try {
    //Read the file and do stuff
} catch(IOException e) {
    e.printStackTrace();
} finally {
    reader.close();
}

then the code in the try-block, including the finally, can all rely on the reader having been created successfully. Otherwise, in your example, if the instantiation fails your code still tries to close the reader, which will still be null, on the way out.

In this changed example the exception thrown by the instantiation of the reader doesn't get handled by the catch block.

A combination of problems led you here, one is you're more worried about trying to squash all the exceptions with one catch block than you are about making sure the reader is in a valid state before you start calling methods on it. (You'll see this one-try-block-to-rule-them-all style a lot in JDBC code where people just can't bear to write all the nested try blocks, it's too ugly to tolerate.) Also, it's very toy-example-ish to catch all the exceptions locally like this, in real life if something goes wrong you want to let the exception be thrown so the rest of the application can know something went wrong, giving you something like

public void doStuffWithFile() throws IOException {
    Reader reader = new FileReader("/my/file/location");
    try {
        //Read the file and do stuff
    } finally {
        try {
            reader.close();
        } catch (IOException e) {
            // handle the exception so it doesn't mask
            // anything thrown within the try-block
            log.warn("file close failed", e);
        }
    }
}

which is very similar to what try-with-resources does. try-with-resources creates the objects first, then executes the try block, then closes the things it created, making sure that any exception thrown on close does not mask an exception thrown in the try-block. Creating the objects still has the potential to throw an exception, it doesn't get handled by the try-with-resources.

public void doStuffWithFile() throws IOException {
    try (Reader reader = new FileReader("/my/file/location")) {
        //Read the file and do stuff
    }
}

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