What does scanner.close() do?

Kootling picture Kootling · Oct 7, 2014 · Viewed 17.8k times · Source

Say I have the following example code:

Scanner scan1 = new Scanner(System.in);    // declaring new Scanner called scan1
int x = scan1.nextInt();    // scan for user input and set it to x
System.out.println(x);    // print the value of x
scan1.close();    // closes the scanner (I don't know exactly what this does)
Scanner scan2 = new Scanner(System.in); // declaring new Scanner called scan1
int y = scan2.nextInt();    // scan for user input and set it to y
System.out.println(y);    // print the value of y

I read the Oracle documentation on the Scanner class and came across this:

When a Scanner is closed, it will close its input source if the source implements the Closeable interface.

Does this mean that once a Scanner (of System.in) is closed, I will no longer be able to use System.in throughout the entire Java program? Or does it mean I will no longer be able to use it throughout the class? Or only the method? Or only its scope?

Another question I have is, is a Scanner restricted to the scope it was declared in (similar to the primitive data types)?

Answer

FatalError picture FatalError · Oct 7, 2014

Yes, it does mean that System.in will be closed. Test case:

import java.util.*;

public class CloseScanner {
    public static void main(String[] args) throws Exception {
        Scanner scanner = new Scanner(System.in);
        scanner.close();
        System.in.read();
    }
}

This code terminates with

$ java CloseScanner 
Exception in thread "main" java.io.IOException: Stream closed
    at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:162)
    at java.io.BufferedInputStream.fill(BufferedInputStream.java:206)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:254)
    at CloseScanner.main(CloseScanner.java:7)

Once closed, you won't be able to use System.in for the rest of your program. The fact that close() is passed through is nice because it means you don't have to maintain a separate reference to the input stream so that you can close it later, for example:

scanner = new Scanner(foo.somethingThatMakesAnInputStream());

You can do that and call .close() on the scanner to close the underlying stream.

In most cases you won't want to close System.in, so you won't want to call .close() in that case.