Comment utiliser java.util.Scanner pour lire correctement la saisie de l'utilisateur du Système.et agir sur elle?
Ce qui est censé être une canonique question/réponse qui peut être utilisé comme un
double cible. Ces exigences sont basées sur les plus communs
questions publiées tous les jours et peuvent être ajoutés au besoin. Ils ont tous
exiger le même code de base de structure pour obtenir pour chacun des scénarios
et ils sont généralement dépendants l'un de l'autre.
Scanner semble comme un "simple" classe à utiliser, et c'est là la première erreur est faite. Il n'est pas simple, il a toutes sortes de la non-évidence d'effets secondaires et aberrante des comportements qui enfreignent les Principe de moindre Étonnement de façon très subtile.
Si cela peut sembler exagéré pour cette classe, mais l'éplucher les oignons, les erreurs et les problèmes sont tous simple, mais pris ensemble, ils sont très complexe en raison de leurs interactions et effets secondaires. C'est pourquoi il ya beaucoup de questions à ce sujet sur un Débordement de Pile tous les jours.
Commune Scanner questions:
Plus Scanner
questions comprennent des tentatives ont échoué à plus d'une de ces choses.
- Je veux être en mesure d'avoir mon programme automatiquement d'attendre la prochaine entrée après chaque saisie précédente.
- Je veux savoir comment faire pour détecter une sortie commande et à la fin de mon programme lorsque cette commande est entrée.
- Je veux savoir comment faire pour correspondre à de multiples commandes pour la sortie de commande dans une casse.
- Je veux être en mesure de faire correspondre les modèles d'expression régulière ainsi que le haut-primitives. Comment, par exemple, pour correspondre à ce qui semble être une date (
2014/10/18
)? - Je veux savoir comment faire correspondre les choses qui pourraient ne pas être facilement mises en œuvre avec l'expression régulière correspondant - par exemple, une URL (
http://google.com
).
Motivation:
Dans le monde Java, Scanner
est un cas particulier, il est extrêmement pointilleux de la classe que les enseignants ne devraient pas donner de nouveaux étudiants instructions d'utilisation. Dans la plupart des cas, les instructeurs ne sais même pas comment l'utiliser correctement. C'est à peine si jamais utilisée dans la production professionnelle de code pour que sa valeur pour les étudiants est extrêmement discutable.
À l'aide de Scanner
implique toutes les autres choses de cette question et de la réponse mentionne. Il n'est jamais sur Scanner
c'est sur la façon de résoudre ces problèmes communs avec Scanner
qui sont toujours co-morbides des problèmes dans presque toutes la question qui se Scanner
mal. Il n'est jamais sur next()
et nextLine()
, qui n'est qu'un symptôme de la finickiness de la mise en œuvre de la classe, il y a toujours d'autres questions dans le code de poster des questions à poser à propos de Scanner
.
La réponse montre de manière complète, idiomatiques de la mise en œuvre de 99% des cas où Scanner
est utilisé et demandé à ce sujet sur StackOverflow.
Surtout en débutant le code. Si vous pensez que cette réponse est trop complexe ensuite se plaindre pour les instructeurs qui racontent des nouveaux étudiants à l'utilisation Scanner
avant d'expliquer les subtilités, les caprices, la non-évidence d'effets secondaires et les particularités de son comportement.
Scanner
est un grand moment d'enseignement sur l'importance de la Principe de moindre étonnement est et pourquoi la cohérence du comportement et de la sémantique sont importants dans le nommage des méthodes et des arguments de méthode.
Note aux étudiants:
Vous aurez probablement jamais voir
Scanner
utilisé dans
professionnel/commercial en ligne d'applications d'entreprise, parce que tout ce qu'il
n'est mieux fait par quelque chose d'autre. Monde réel, le logiciel doit être
plus résistant et plus facile à gérer queScanner
vous permet d'écrire
code. Monde réel logiciel utilise le format de fichier normalisé d'analyseurs et de
documenté les formats de fichier, pas le adhoc formats d'entrée que vous êtes
donné en stand alone affectations.
OriginalL'auteur | 2014-10-19
Vous devez vous connecter pour publier un commentaire.
Idiomatiques Exemple:
Voici comment utiliser correctement le
java.util.Scanner
classe interactive à la lecture du mode d'entrée deSystem.in
correctement( parfois appeléstdin
, en particulier en C, C++ et d'autres langues ainsi que dans les environnements Unix et Linux). Il idiomatique montre le plus commun de choses qui doivent être fait.Notes:
Ci-dessous sont quelques-uns des choses que je pensais quand j'ai écrit cet exemple:
Version du JDK:
J'ai volontairement gardé cet exemple compatible avec le JDK 6. Si certains scénario vraiment exigences d'une fonction de JDK 7/8 je ou quelqu'un d'autre va poster une nouvelle réponse avec des détails sur la façon de modifier cette version du JDK.
La majorité des questions au sujet de cette classe viennent d'étudiants, et ils ont généralement des restrictions sur ce qu'ils peuvent utiliser pour résoudre un problème donc j'ai limité autant que je pouvais pour montrer comment faire les choses en commun, sans autres dépendances. Dans les 22 ans que je travaille avec Java et de consultation de la majorité de l'époque, je n'ai jamais rencontré une utilisation professionnelle de cette classe dans les 10 millions de lignes de code source que j'ai vu.
, Le traitement des commandes:
Cette montre exactement comment idiomatique les commandes de lecture de l'utilisateur de manière interactive et d'expédier les commandes. La majorité des questions au sujet de
java.util.Scanner
sont de la comment puis-je obtenir mon programme pour arrêter de fumer quand j'ai entrer certains de saisie spécifiques à catégorie. Cela montre clairement.Naïf Répartiteur
L'envoi de la logique est volontairement naïf pour ne pas compliquer la solution pour les nouveaux lecteurs. Un répartiteur basé sur un
Strategy Pattern
ouChain Of Responsibility
modèle serait plus approprié pour les problèmes du monde réel qui serait beaucoup plus complexe.Erreur De Manipulation
Le code a été délibérément structuré qu'elle ne nécessite aucune
Exception
la manipulation, car il n'y a pas de scénario où certaines données peuvent ne pas être correcte..hasNext()
et.hasNextXxx()
J'ai rarement vu quelqu'un à l'aide de la
.hasNext()
correctement, par un test de dépistage pour le générique.hasNext()
de contrôle de la boucle d'événements, puis à l'aide de laif(.hasNextXxx())
idiome vous permet de décider comment et quoi de procéder avec votre code sans avoir à se soucier de demander uneint
lorsqu'aucun n'est disponible, donc pas de code de gestion des exceptions..nextXXX()
vs.nextLine()
C'est quelque chose qui brise tous les code. C'est un méticuleux du détail qui ne devraient pas être traitées et a une très obfusated bug qui est difficile à comprendre à cause de cela rompt le Principal de Moins d'Étonnement
La
.nextXXX()
méthodes ne consomment pas de la fin de ligne..nextLine()
.Qui signifie que l'appel
.nextLine()
immédiatement après.nextXXX()
sera juste retour de la fin de ligne. Il faut l'appeler de nouveau à réellement obtenir la ligne suivante.C'est pourquoi beaucoup de gens le défenseur utiliser rien d'autre que la
.nextXXX()
méthodes ou seulement.nextLine()
mais pas les deux en même temps, de sorte que ce comportement capricieux ne pas vous passionner. Personnellement, je pense que le type de méthodes sécuritaires sont beaucoup mieux que d'avoir à tester et analyser et de repérer les erreurs manuellement.Immutablity:
Avis qu'il n'y a pas mutable variables utilisées dans le code, c'est important d'apprendre à le faire, il élimine quatre des plus grandes sources d'erreurs d'exécution et les bogues subtils.
Pas
nulls
signifie pas de possibilité d'uneNullPointerExceptions
!Pas de mutabilité signifie que vous n'avez pas à vous soucier des arguments de méthode de changer ou quoi que ce soit d'autre en train de changer. Lors de l'étape de débogage à travers vous ne jamais avoir à utiliser
watch
pour voir quelles sont les variables changent pour quelles valeurs, si elles sont en train de changer. Cela rend la logique 100% déterministe quand vous la lisez.Pas de mutabilité signifie que votre code est automatiquement thread-safe.
Pas d'effets secondaires. Si rien ne peut le changer, vous n'avez pas à vous inquiéter au sujet de certains de subtils effets secondaires de certains cas limites de changer quelque chose, de façon inattendue!
Lisez ceci si vous ne comprenez pas comment appliquer le
final
mot clé dans votre propre code.L'aide d'un Jeu au lieu de massive
switch
ouif/elseif
blocs:Avis comment je utiliser un
Set<String>
et l'utilisation.contains()
de classer les commandes à la place d'un massif deswitch
ouif/elseif
monstruosité qui serait gonfler votre code et, plus important encore faire de l'entretien un cauchemar! L'ajout d'une nouvelle surcharge de commande est aussi simple que l'ajout d'un nouveauString
de la matrice dans le constructeur.Ce serait aussi très bien fonctionner avec
i18n
eti10n
et la bonneResourceBundles
.Un
Map<Locale,Set<String>>
serait vous permettent de prendre en charge plusieurs langues, avec très peu de frais généraux de!@Non
J'ai décidé que tout mon code devrait explicitement déclarer si quelque chose est
@Nonnull
ou@Nullable
. Elle permet à votre IDE de vous avertir sur le potentiel deNullPointerException
dangers et quand vous n'avez pas à vérifier.Le plus important des documents de l'attente pour les futurs lecteurs qu'aucun de ces paramètres de la méthode doit être
null
.Appel .close()
Vraiment réfléchir avant de le faire.
Que pensez-vous qui va arriver
System.in
si vous appelezsis.close()
? Voir les commentaires dans la liste ci-dessus.Veuillez fourche et envoyer des pull requests et je mettrai à jour cette question et la réponse pour les autres scénarios d'utilisation.
OriginalL'auteur