Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
271 views
in Technique[技术] by (71.8m points)

java - Should a Scanner only be instantiated only once? if that's the case why so?

I know I'm going out on a limb here, but I just can't seem to understand why can't we just create an instance of the Scanner class twice. I'll add an example just in case.

import java.util.Scanner;

public class Nope
{
    public static void main(String[] args)
    {
        System.out.println("What's your name?");
        Scanner scanner = new Scanner(System.in);
        String name = scanner.nextLine();
        
        System.out.println("Welcome " + name + "!");
        scanner.close();
        
        // Now 
        System.out.println("where you do live?");
        Scanner sc = new Scanner(System.in);
        String country = sc.nextLine();
        
        System.out.println("That's a lovely place");
        sc.close();
        
    }
}

And I get a runtime error which looks something like this

What's your name?
Kate
Welcome Kate!
Exception in thread "main" where you do live?
java.util.NoSuchElementException: No line found
    at java.base/java.util.Scanner.nextLine(Scanner.java:1651)
    at Nope.main(Nope.java:17)

I know it doesn't make sense to create a new object again of the same class, encouraging redundancy. But I just think it will clear my mind if I know why, don't you think so too?

What does the machine mean by 'java.util.NoSuchElementException: No line found' and people are saying Scanner ain't cloneable.

PS: I intentionally closed my first scanner and created a new object just to understand the issue.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There are actually two separate things going on here.

  1. You should create one Scanner per input source. For example, one Scanner for each distinct input file, one for System.in, one for each distinct socket input stream.

    The reason is (as Chrylis points out) is that various methods of Scanner read ahead on the scanner's input source. If the characters are not consumed by the operation, they are not put back into the input source. Rather they are buffered by the Scanner, and kept for the next Scanner operation to use. So if you have two Scanners trying to read from the same input source, one may steal input intended for the other.

    This is the real reason why opening multiple Scanner objects on System.in is bad. Not the "redundancy" argument that you proposed. There is nothing fundamentally wrong with a bit of redundancy ... especially if it simplifies the application. But scanners competing for input may result in unexpected behavior / bugs.

  2. The second problem is that when you close() a Scanner that also closes the input source.

    In your case that means that you are closing System.in. And then you are creating a second Scanner to read from the (now closed) System.in.

    When you attempt to us a Scanner to read from a closed System.in, that leads to a NoSuchElementException.

So if you hadn't called close() on the first Scanner, your code might have worked, but that would depend on the sequence of operations you made on the first Scanner.


People are saying Scanner ain't cloneable.

They are correct.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

56.9k users

...