Java – Why an Instance of Scanner Class is Needed for Input

javaobject-oriented

Java is object oriented, but, why do we need to create an object from the Scanner Class to get input? Couldn't next() methods, for example, just be Static?

C looks to me pretty simpler as you just use scanf(), gets() or fgets().
I'm sure there's a reason for Java developers for creating the Scanner class, but how is it better than just having a normal function to do the work?

I've found this link that may seem asking the same question, but answers are just about

"you need to create an object because is not static"…

My guess is: since Java is Object Oriented, they decided to put all input methods in a class. They didn't do static methods so you can have all kind of different sources (keyboard Input, file Input…) in different objects ?

I would appreciate if someone can edit the question to make it sound more clear!

Best Answer

The answer is "because a scanner has state."

Looking at the code for java.util.Scanner, you will see a number of private fields such as a buffer and its associated information, a Matcher, a Pattern, an input source, information about if the source is closed or not, the type of the last thing matched, information about if the last thing was a valid match or not, the radix used for numbers, the locale (information about if you are using . or , as a thousands separator), and its own LRU cache for recently used patterns, the information about the last exception that was encountered, some information about parsing numbers, some information about parsing booleans, quite a bit more information about parsing integers... and I think thats about it.

As you can see, thats a fairly large block of text there. That is the state of the Scanner. In order to make the Scanner into a static class, that state would need to be stored somewhere else. The C way of doing it really doesn't have that much state with it. You've got a fscanf. The FILE maintains some state about the position it is at (but that needs to be passed in for each invocation of fscanf). If there was an error, you have to process it (and then you start writing code that looks like this) - and that doesn't tell you information like "I was expecting an Integer, but found a String."

When one looks at the theoretically static Scanner - all of the state is maintained outside of the class, it isn't encapsulated within the class. Other bits of code could tinker with those variables. When other code can tinker with the state of the class, it becomes very difficult to reason about what the class will do in any given situation.

You could, maybe, write something like ScannerState { Locale loc; ... } and have code that results in:

ScannerState state = new ScannerState(a whole lot of arguments);
int foo = Scanner.nextInt(state);

But then, this is much more cumbersome than having the state encapsulated within a Scanner object in the first place (and not needing to pass in the state).

Lastly, the Scanner implements the interface of Iterator<String> which means that one can use it in code such as:

Scanner in = new Scanner(someFile);
whie(in.hasNext()) { ... }

Without being able to get an instance of the Scanner class, this type of structure becomes more cumbersome within an object oriented language.

Related Topic