Scanner useLocale Resource leak

392 views Asked by At

Hello my fellow programmers.

I have some code which the spring tool suite editor responds differently too, maybe some of you smart people know why.

File inputFile = new File(System.getProperty("user.home") + "/Desktop/Input.txt");
    Scanner sc = null;
    double payment=0;
    try {
        sc = new Scanner(inputFile).useLocale(Locale.ENGLISH);
        //sc = new Scanner(inputFile)
        //sc.useLocale(Locale.ENGLISH);
        payment = sc.nextDouble();
    } catch (Exception e) {
    } finally {
        if (sc != null) {
            sc.close();
        }
    }

Can someone tell me why this is not possible:

Scanner sc = new Scanner(inputFile).useLocale(Locale.ENGLISH);

but this is!?

Scanner sc = new Scanner(inputFile);
sc.useLocale(Locale.ENGLISH)

the first line up code gives me a warning "Resource leak: unassigned closeable value is never closed", and as you can see i've in my try/catch used a finally which should always close my object if it's not null.

Thank you in advance.

2

There are 2 answers

2
Kayaman On BEST ANSWER

It's the compiler warning you about something it doesn't (or rather can't) understand.

When useLocale() is called, the same Scanner instance it was called on is returned. However the compiler can't know that and issues a warning. If the method returned a different Scanner object, the resource leak would be valid as the original Scanner object would have disappeared without being closed.

An unwarranted warning, that you may ignore.

3
Stephen C On

Kayaman has identified one problem. Another is that the useLocale() call could (in theory1) throw an exception. If that happened, sc would not be assigned ... and the Scanner would not be closed. That is a warranted warning!

Either way, the correct way to write this code is as follows:

File inputFile = new File(....);
double payment = 0;
try (Scanner sc = new Scanner(inputFile)) {
    sc.useLocale(Locale.ENGLISH);
    payment = sc.nextDouble();
} catch (IOException e) {
    // Do something about it
}

Note that the try-with-resources takes care of the closing, and I do NOT catch and squash java.lang.Exception. (Catching Exception is bad. Squashing it is even worse.)

And this version is fewer lines of code. More concise and more correct == big win!


1 - I looked at the source code, and I can see ways that you could get an NPE or an OOME in a useLocale() call.