2

I am getting an error when I initialize the Scanner: the code turns italic and blue as soon as I type a semicolon.

The error message says:

Resource leak: 'in' is never closed.

How can I avoid this error?

My code looks like this:

import java.util.Scanner;

public class Zoezi9 {

    public static void main(String[] args) {
        double cm;
        int feet, inches, remainder;
        final double CM_PER_INCH = 2.54;
        final int IN_PER_FOOT = 12;
        Scanner in = new Scanner(System.in);

        System.out.print("How many cm?; ");
        cm = in.nextDouble();
        inches = (int) (cm/CM_PER_INCH);
        feet = inches/IN_PER_FOOT;
        remainder = inches % IN_PER_FOOT;

        System.out.printf("%.2f cm = %d ft, %d in\n",cm,feet,remainder);

    }
}
slartidan
  • 17,225
  • 11
  • 70
  • 109
Katanaj
  • 21
  • 1

2 Answers2

1

Certain resources require special handling, when using them the wrong way, you risk resource leaks.

For example: when you open a file, the underlying operating system provides a file handle to the JVM. When you forget to properly "return" that file handle after your code is done using it ... that isn't a problem when it happens once. But assume your application keeps running for hours, days, weeks. Then such things add up. And worst case, at some point, you run out of that resource, and then that JVM crashes.

System.in is an InputStream, and InputStreams can be such resources. Now your editor tries to help you: it notices that you use some InputStream, but hey, you never call close on it.

In your case, it is safe to ignore that message though. In the "real world", you typically avoid such pitfalls by using try-with-resource construct. That one takes care of closing the used resource after you are done using it.

And to follow up on the comment by Andy Turner: you don't just blindly close anything that can be closed. Typically, a component manages those resources that it created itself. System.in isn't owned by your class, and it wasn't opened by your class. So, conceptually, it would be wrong to have your class close it.

Beyond that, what exactly gets "warned" at depends on your editor/IDE and the settings you put in place. So you might be able to simply disable this warning there. Depending on the kind of warning you get, there is also @SuppressWarnings. And an even better fit: @WillNotClose!

GhostCat
  • 127,190
  • 21
  • 146
  • 218
  • 2
    But you shouldn't close `System.in`, or indeed any stream that you don't own (which usually means "that you didn't create"). A check which simply says "all scanners must be closed" over-simplifies it: you don't need to close a Scanner created with a string, and you shouldn't close a Scanner constructed with an already-existing stream. – Andy Turner Oct 12 '18 at 06:48
  • 1
    Just for record, there are annotations like javax.annotation.WillNotClose and javax.annotation.WillClose which make your intents explicit to IDE (or other static analysis tools). They are just hints, but can prevent such warnings. – rkosegi Oct 12 '18 at 07:05
  • @AndyTurner Good observation. Updated the answer accordingly. – GhostCat Oct 12 '18 at 08:11
  • @rkosegi One never stops learning; I didn't know about this annotation. Added a link to my answer - thanks! – GhostCat Oct 12 '18 at 08:12
1

Scanner implements the interface Closable, which extends AutoClosable. This is a new and convinient way of telling java, that a Scanner should be closed at a certain point - whatever happens after it has been opened.

In your case, you should not use this feature. Closing System.in will prevent you from using it later again.

When using other inputs sources, however, it would be required / recommended.

If you want to use it, you can use this syntax:

try (Scanner in = new Scanner(<some other input source that requires closing>)) { // open Scanner
    // use Scanner
} // close Scanner, even if an exception was risen in the meanwhile
slartidan
  • 17,225
  • 11
  • 70
  • 109
  • 1
    Actually, closing the Scanner in this case can be detrimental as it will also "close the underlying Readable" (doc) - in this case, `System.in` so you won't be able to read from stdin anymore. – daniu Oct 12 '18 at 07:05