La réponse est "parce qu'un scanner a un état".
En regardant le code de java.util.Scanner , vous verrez un certain nombre de champs privés tels qu'un tampon et ses informations associées, un Matcher, un Pattern, une source d'entrée, des informations sur si la source est fermée ou non, le type de la dernière chose trouvée, des informations sur si la dernière chose était une correspondance valide ou non, la base utilisée pour les nombres, les paramètres régionaux (informations sur si vous utilisez .
ou ,
comme séparateur de milliers) et son propre cache LRU pour les modèles récemment utilisés , les informations sur la dernière exception qui a été rencontrée, quelques informations sur l'analyse des nombres, des informations sur l'analyse des booléens, un peu plus d'informations sur l'analyse des entiers ... et je pense que c'est tout.
Comme vous pouvez le voir, c'est un bloc de texte assez important. Tel est l'état du scanner. Afin de faire du Scanner une classe statique, cet état devrait être stocké ailleurs. La manière C de le faire n'a vraiment pas beaucoup d'état avec elle. Vous en avez un fscanf
. Le FICHIER conserve un état sur la position à laquelle il se trouve (mais cela doit être transmis pour chaque invocation de fscanf
). S'il y a eu une erreur, vous devez la traiter (et ensuite vous commencez à écrire du code qui ressemble à ceci ) - et cela ne vous dit pas des informations comme "je m'attendais à un entier, mais j'ai trouvé une chaîne".
Quand on regarde le scanner théoriquement statique - tout l'état est maintenu en dehors de la classe, il n'est pas encapsulé dans la classe. D'autres bits de code pourraient bricoler ces variables. Lorsqu'un autre code peut bricoler l'état de la classe, il devient très difficile de raisonner sur ce que la classe fera dans une situation donnée.
Vous pourriez peut-être écrire quelque chose comme ScannerState { Locale loc; ... }
et avoir du code qui se traduit par:
ScannerState state = new ScannerState(a whole lot of arguments);
int foo = Scanner.nextInt(state);
Mais alors, c'est beaucoup plus lourd que d'avoir l'état encapsulé dans un objet Scanner en premier lieu (et de ne pas avoir besoin de passer l'état).
Enfin, le Scanner implémente l'interface Iterator<String>
ce qui signifie que l'on peut l'utiliser en code tel que:
Scanner in = new Scanner(someFile);
whie(in.hasNext()) { ... }
Sans pouvoir obtenir une instance de la classe Scanner, ce type de structure devient plus encombrant dans un langage orienté objet.
FILE*
(l'état de position) en C.Iterator
- nonIterable
. Il est impossible d'utiliser Scanner en boucle améliorée.réponse courte: non. Vous pouvez obtenir une entrée utilisateur sans utiliser d'instance de scanner.
Par exemple: https://docs.oracle.com/javase/tutorial/essential/io/cl.html ou
http://alvinalexander.com/blog/post/java/java-source-code-read-command-line -contribution
la source
String orgName = (new BufferedReader(new InputStreamReader(System.in))).readLine();
C'est horriblement alambiqué par rapport à l'utilisation d'unScanner
et crée également de nouvelles instances non pas d'un mais de deux objets juste pour les jeter immédiatement.