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.