Search code examples
java-8compiler-errorstry-catch-finallytry-with-resources

finally block - variable cannot be resolved


Java 8

import java.util.zip.GZIPOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;


private void createFile(final String json) throws IOException {
        final String fileName = getConfigFileName(this.getSomePath());
        GZIPOutputStream out = null;
        try {
            out = new GZIPOutputStream(new FileOutputStream(fileName + ".gz"));
            out.write(json.getBytes());
        } catch (IOException e) {
            throw e;
        } finally {
            try {
                if (out != null) {
                    out.finish();
                    out.close();
                }
            } catch (IOException e) {
                LOGGER.error("createFile: IOException while closing resources", e);
            }
        }
    }

Nice. This work fine. Now I want to use try-with-resource

private void createFile(final String json) throws IOException {
    final String fileName = getConfigFileName(this.getSomeFile());
    try (GZIPOutputStream out = new GZIPOutputStream(new FileOutputStream(fileName + ".gz"))) {
        out.write(json.getBytes());
    } catch (IOException e) {
        throw e;
    } finally {
        try {
            if (out != null) {
                out.finish();
            }
        } catch (IOException e) {
            LOGGER.error("createFile: IOException while closing resources", e);
        }
    }
}

But now I get error in this line:

if (out != null) {

Error is:

out cannot be resolved

I know this error is rise because variable out is on finally section. But how I can use try-with-resources and execute method out.finish ?


Solution

  • From a technical perspective - a variable declared in the try argument isn't available in the finally clause, as you've seen. The good news here is that from a function perspective - finish() shouldn't be in the finally block anyway. finish is part of the positive (a.k.a "happy") flow, and should only be called when you're done writing to the stream. In other words, if the write operation failed and an exception was thrown, you shouldn't call finish anyway.

    To make a long story short - move the finish call inside the try block:

    Side note: Since your method throws an IOException, there's no reason to catch the exception and rethrow it. You can clean up the code by allowing it to be thrown from the method call directly:

    private void createFile(final String json) throws IOException {
        final String fileName = getConfigFileName(this.getSomeFile());
        try (GZIPOutputStream out = new GZIPOutputStream(new FileOutputStream(fileName + ".gz"))) {
            out.write(json.getBytes());
            out.finish();
        }
    }