0

After using the scanner.close() method, I cannot open another scanner. I have searched my question on google to only find people giving a solution for a workaround. I just want to understand why this is a problem in the first place. can anyone explain why?

import java.util.Scanner;

public class Main {

    public static Scanner scan = new Scanner(System.in);

    public static void main(String[] args) {
        scan.close();

        Scanner scan = new Scanner(System.in);

        System.out.println(scan.next());  //NoSuchElementException
    }

}

I understand that having multiple scanners open at once can result in an outOfMemoryError, so I thought why not have it as a singleton utility class that you can call methods from? This class would open and close a scanner with each use so that streams do not need to remain open.

public class Main {

    public static void main(String[] args) {
        LinkedList<Scanner> list = new LinkedList<>();
        while(true) {
            list.add(new Scanner(System.in)); //OutOfMemoryError
        }
    }
}

which comes back to the root of my question, If we can all understand why the scanner class works this way, perhaps we could come up with a solution?

PanderIT
  • 11
  • 1
  • You can, but you closed `System.in`, so you can't read anything from it. The real question is why close it at all? If you're going to need another one, why not keep using the same one? – user207421 Oct 05 '19 at 04:28
  • I simply just want to for the sake of exploration. I already know how to use the same one. I'm just looking further into the Scanner class and how it works, and why I can't re-open System.in once it is closed. – PanderIT Oct 09 '19 at 01:01

1 Answers1

7

From the documentation for Scanner.close():

if its underlying readable also implements the Closeable interface then the readable's close method will be invoked.

So when you close the scanner, it's also closing System.in, which means you can't later make a new scanner from it, since you can't reopen a stream once it's closed.

And you're only getting an OutOfMemoryError in your second example because you're trying to allocate an infinite number of scanners and preventing them from being garbage collected, not because scanners are particularly heavyweight.

  • I added the example for OutOfMemoryError to show that there could be a better efficiency by being able to open and close a scanner when needed rather than keep one open until the program finishes execution. So what youre saying is that its not the scanner.close() method that is the problem, I am getting an NoSuchElementException because once System.In is closed I cannot reopen another System.in stream. – PanderIT Oct 05 '19 at 02:59
  • That makes no sense. And I'm saying that it IS the scanner.close() method that's the problem. – Joseph Sible-Reinstate Monica Oct 05 '19 at 03:01
  • " it's also closing System.in, which means you can't later make a new scanner from it, since you can't reopen a stream once it's closed." Why cant we open a new stream once it is closed? – PanderIT Oct 05 '19 at 03:05
  • I appreciate your efforts in guidance @Joseph Sible. your answer has given me a new question and has put me on a search for more answers, Ive found another source. https://stackoverflow.com/questions/27286690/in-java-is-it-possible-to-re-open-system-in-after-closing-it – PanderIT Oct 05 '19 at 03:15
  • @PanderIT You can't reopen a closed stream because there is no API for it. – user207421 Oct 05 '19 at 04:29