DroidOS DroidOS - 7 months ago 14
Java Question

Java Scoping & Visibility Rules

I am coming back to writing code in Java after a long gap - most of my coding work over the past few years has been in PHP & JavaScript - and am discovering that I have to work harder to satisfy the Java compiler which is far more rigorous about issues such as variable scope and exception handling. A piece of code that caused me some trouble is shown below

File file = new File(path, fname);
FileOutputStream stream = null;
try
{
stream = new FileOutputStream(file);
stream.write(tosave.getBytes());
}
finally
{
try
{
if (null != stream) {stream.close();}
return true;
}
catch(Exception e){return false;}
}


This is accepted by the compiler. However, before I got here I had run into several issues.


  • First attempt: No Catch Block. The compiler refused to play ball because it wanted me to deal with the eventuality that the FileOutputStream could not be created. Ditto for writing to that stream. I understand the logic behind this reasoning and like it.

  • Second attempt: Catch Block but...:I was declaring and creating the
    stream
    variable INSIDE the
    try
    block. The compiler threw a wobbly again - the
    stream
    variable was out-of-scope in the
    finally
    block.



As you will see I have gotten around the issue by declaring
stream
above the
try
block and initializing it to null.

This works. However, given just how rusty my Java skills are I thought I would ask: Is there a right way to write such code?

Answer

The idiomatic way to handle such scenarios in modern Java versions (since Java 7) would be to use a try-with-resource block that handles all the ugly closing "logic" for you. You'd still have to either catch the exception or propagate it upwards, but that's a relatively small issue. Consider the following:

public static boolean writeToFile(String path, String fname) {
    File file = new File(path, fname);
    try (FileOutputStream stream = new FileOutputStream(file)) {
        stream.write(tosave.getBytes());
    } catch (IOException e) {
        // Should probably log the exception too
        return false;
    }
    return true;
}
Comments