Search code examples
pythonjavamemory-leaksioresources

Java | Safest way to close resources


Question

What's the best way / safest way to close a 'i/O resource' in Java?

Context

Coming from python background, which uses the with which creates a Context Manager statement to Reading and Writing Files, it ensures that, the resource of the context if closed/cleanedup (technically this can be anything, but built in io operations for instance will do a close once it goes out of scope, even sockets)

So taking this code:

file = open('workfile', encoding="utf-8")
read_data = f.read()
file.close()

The recommended way is using the with statement

with open('workfile', encoding="utf-8") as file:
    read_data = file.read()

By the time we exit the with scope (which is literally, the previous indentation level) even if an error occurred, the file will always be closed

Sure we could do this

try:
    file = open('workfile', encoding="utf-8")
    read_data = f.read()
except Exception as _: 
    pass
finally:
    file.close()

But, most cases, a context manager is better. One reason is that, simply someone may forget to write down the file.close() but also, is simply more clean and safe.

Java example code

Now in java, what is the recommended, similar why to handle this?

Taking as example the Scanner:

public class App 
{
    public static void main( String... args )
    {
        Scanner reader = new Scanner(System.in);
        try {
            System.out.print(">>> username: ");
            if (reader.hasNextLine()) {
                String username = reader.nextLine();
                System.out.format("Hello %s", username);
            }
        } catch (Exception error) {
            System.out.format("Error while reading scanner %s", error);
        } finally {
            reader.close();
        }


    }
}

As you can see, this is how I am handling it,

is this the java way?


Solution

  • I think you can use try(...){...}catch{} statement (try with resource statement).

    for example:

    try (
               Scanner reader = new Scanner(System.in);
               // other resource initalization
     ) {
                System.out.print(">>> username: ");
                if (reader.hasNextLine()) {
                    String username = reader.nextLine();
                    System.out.format("Hello %s", username);
                }
            } catch (Exception error) {
                System.out.format("Error while reading scanner %s", error);
            }
    

    Since JDK 1.7, the () after try is used to initialize one or more resources that must be closed after the program ends. This approach does not require a finally block