This is meant to be a canonical question/answer that can be used as a duplicate target. These requirements are based on the most common questions posted every day and may be added to as needed. They all require the same basic code structure to get to each of the scenarios and they are generally dependent on one another.
Scanner seems like a "simple" class to use, and that is where the first mistake is made. It is not simple, it has all kinds of non-obvious side effect and aberrant behaviors that break the Principle of Least Astonishment in very subtle ways.
So this might seem to be overkill for this class, but the peeling the onions errors and problems are all simple, but taken together they are very complex because of their interactions and side effects. This is why there are so many questions about it on Stack Overflow every day.
Common Scanner questions:
Most Scanner
questions include failed attempts at more than one of these things.
I want to be able to have my program automatically wait for the next input after each previous input as well.
I want to know how to detect an exit command and end my program when that command is entered.
I want to know how to match multiple commands for the exit command in a case-insensitive way.
I want to be able to match regular expression patterns as well as the built-in primitives. For example, how to match what appears to be a date (
2014/10/18
)?I want to know how to match things that might not easily be implemented with regular expression matching - for example, an URL (
http://google.com
).
Motivation:
In the Java world, Scanner
is a special case, it is an extremely finicky class that teachers should not give new students instructions to use. In most cases the instructors do not even know how to use it correctly. It is hardly if ever used in professional production code so its value to students is extremely questionable.
Using Scanner
implies all the other things this question and answer mentions. It is never just about Scanner
it is about how to solve these common problems with Scanner
that are always co morbid problems in almost all the question that get Scanner
wrong. It is never just about next()
vs nextLine()
, that is just a symptom of the finickiness of the implementation of the class, there are always other issues in the code posting in questions asking about Scanner
.
The answer shows a complete, idiomatic implementation of 99% of cases where Scanner
is used and asked about on StackOverflow.
Especially in beginner code. If you think this answer is too complex then complain to the instructors that tell new students to use Scanner
before explaining the intricacies, quirks, non-obvious side effects and peculiarities of its behavior.
Scanner
is the a great teaching moment about how important the Principle of least astonishment is and why consistent behavior and semantics are important in naming methods and method arguments.
Note to students:
You will probably never actually see
Scanner
used in professional/commercial line of business apps because everything it does is done better by something else. Real world software has to be more resilient and maintainable thanScanner
allows you to write code. Real world software uses standardized file format parsers and documented file formats, not the adhoc input formats that you are given in stand alone assignments.
Idiomatic Example:
The following is how to properly use the
java.util.Scanner
class to interactively read user input fromSystem.in
correctly( sometimes referred to asstdin
, especially in C, C++ and other languages as well as in Unix and Linux). It idiomatically demonstrates the most common things that are requested to be done.Notes:
Below are some of the things I was thinking about when I wrote this example:
JDK Version:
I purposely kept this example compatible with JDK 6. If some scenario really demands a feature of JDK 7/8 I or someone else will post a new answer with specifics about how to modify this for that version JDK.
The majority of questions about this class come from students and they usually have restrictions on what they can use to solve a problem so I restricted this as much as I could to show how to do the common things without any other dependencies. In the 22+ years I have been working with Java and consulting the majority of that time I have never encountered professional use of this class in the 10's of millions of lines source code I have seen.
Processing commands:
This shows exactly how to idiomatically read commands from the user interactively and dispatch those commands. The majority of questions about
java.util.Scanner
are of the how can I get my program to quit when I enter some specific input category. This shows that clearly.Naive Dispatcher
The dispatch logic is intentionally naive so as to not complicate the solution for new readers. A dispatcher based on a
Strategy Pattern
orChain Of Responsibility
pattern would be more appropriate for real world problems that would be much more complex.Error Handling
The code was deliberately structured as to require no
Exception
handling because there is no scenario where some data might not be correct..hasNext()
and.hasNextXxx()
I rarely see anyone using the
.hasNext()
properly, by testing for the generic.hasNext()
to control the event loop, and then using theif(.hasNextXxx())
idiom lets you decide how and what to proceed with your code without having to worry about asking for anint
when none is available, thus no exception handling code..nextXXX()
vs.nextLine()
This is something that breaks everyone's code. It is a finicky detail that should not have to be dealt with and has a very obfusated bug that is hard to reason about because of it breaks the Principal of Least Astonishment
The
.nextXXX()
methods do not consume the line ending..nextLine()
does.That means that calling
.nextLine()
immediately after.nextXXX()
will just return the line ending. You have to call it again to actually get the next line.This is why many people advocate either use nothing but the
.nextXXX()
methods or only.nextLine()
but not both at the same time so that this finicky behavior does not trip you up. Personally I think the type safe methods are much better than having to then test and parse and catch errors manually.Immutablity:
Notice that there are no mutable variables used in the code, this is important to learn how to do, it eliminates four of the most major sources of runtime errors and subtle bugs.
No
nulls
means no possibility of aNullPointerExceptions
!No mutability means that you don't have to worry about method arguments changing or anything else changing. When you step debug through you never have to use
watch
to see what variables are change to what values, if they are changing. This makes the logic 100% deterministic when you read it.No mutability means your code is automatically thread-safe.
No side effects. If nothing can change, the you don't have to worry about some subtle side effect of some edge case changing something unexpectedly!
Read this if you don't understand how to apply the
final
keyword in your own code.Using a Set instead of massive
switch
orif/elseif
blocks:Notice how I use a
Set<String>
and use.contains()
to classify the commands instead of a massiveswitch
orif/elseif
monstrosity that would bloat your code and more importantly make maintenance a nightmare! Adding a new overloaded command is as simple as adding a newString
to the array in the constructor.This also would work very well with
i18n
andi10n
and the properResourceBundles
. AMap<Locale,Set<String>>
would let you have multiple language support with very little overhead!@Nonnull
I have decided that all my code should explicitly declare if something is
@Nonnull
or@Nullable
. It lets your IDE help warn you about potentialNullPointerException
hazards and when you do not have to check.Most importantly it documents the expectation for future readers that none of these method parameters should be
null
.Calling .close()
Really think about this one before you do it.
What do you think will happen
System.in
if you were to callsis.close()
? See the comments in the listing above.Please fork and send pull requests and I will update this question and answer for other basic usage scenarios.