1-4 Getting User Input

The IPO Model

Every program ever written follows a design pattern called the Input-Processing-Output Model (IPO).

Typically, input for a program comes from the keyboard (i.e., System.in) but it might also come from a file or some other source – we call these input streams. The processing stage takes the input and performs various operations on it (e.g., arithmetic). Output typically displays the result on the screen (i.e., System.out) but might also write to a file – we call these output streams.

The Scanner Class

The Java API provides a huge library of classes that are organized into packages. For convenience, the Java compiler automatically imports a package of classes called java.lang. This package contains classes such as System and Math that are almost always needed when writing Java programs. Because not all programs require keyboard input you must import the Scanner class (found in the java.util package) yourself before you can use its methods. Let’s look at an example:

In the output below, yellow indicates sample user input.

What is your full name: Vik 20
How old are you: 17
Well, Vik 20, you are 17 years old.

Line 1 imports the Scanner class, which is stored in the package java.util. Any import statements should always appear at the top of your code (before the header comment) and cannot appear inside a class definition.

The java.util package contains other commonly useful classes, particularly related to String processing and data structures. To import them all at once you might see examples online that go something like this:

Don’t do it!  This is poor style and lazy programming. For readability, it’s always best to import each required class using a separate import statement. Why import a bunch of classes that you don’t need?

Line 6 uses the new keyword to instantiate (create) a Scanner object linked to System.in (i.e., the keyboard). The left side of the assignment statement declares a reference variable called input to refer to that Scanner object in memory. To call methods in our Scanner object we then use input. followed by the method we’d like. This works much like the Math class except we did not have to instantiate a Math object for reasons I’ll explain later.

Each keystroke that the user types (including the newline, \n) gets appended to an input stream. As the name implies, an input stream is just a series of characters. A sequence of characters separated by whitespace characters (blank space, tab, or newline) is called a token, so an input stream may have several tokens on it ready to be read. For example, here’s what (conceptually) the input stream would look like for the sample run above:

There are three tokens in the input stream above, each terminated by a blank space or newline (\n) character; i.e., the <Return> key. Depending on what you’d like to read next from the stream there are different Scanner methods you can call. Line 13 calls the nextLine() method that will read all tokens from the input stream up to the next newline character (i.e., the \n) and return them as one string (i.e., “Vik 20”).

The nextInt() method call on line 15 reads the next token and returns it as an int (i.e., 17). The Scanner class also includes a method called next(), which reads the next token (1 word) of input as a string, and nextDouble() that reads the next token as a double value.

You might have also noticed on line 17 that instead of using the println() method, which moves to the beginning of the next line after it displays a string, I have used the print() method that does not go to the next line automatically. This is useful so that our prompts and user input can happen on the same line in the Dr Java interactions pane.

Watch Out!

Try running this program and entering a non-integer value when prompted for age. The program will crash and display a long error message called an exception, in this case, an InputMismatchException. An exception is another type of error called a run-time error. A run-time error happens when a program encounters unexpected input that it is unable to deal with. This is different from the syntax and logic errors we’ve seen.

In this case, the nextInt() method is designed to read and return an integer value (only). If we enter some other type of data a run-time error crashes our code. This is undesirable! Later, I’ll show you how to deal with exceptions so that our programs can recover without crashing like this.

Watch Out Again!

Try changing the code so that the age is input first, followed by the name, like so:

If you run this program you’ll see that there is now a logic error. When reading a String after an int something unexpected happens — the user doesn’t get a chance to enter their name, the program seems to skip this input and displays the output with an empty string for their name. The output looks like this:

How old are you: 17
What is your full name: Well, , you are 17 years old.

The reason this happens is that the nextInt() method only reads digits (for an int) from the stream, it does not remove the newline (\n) that the user typed after their age:

1-4-InputStream2The arrow indicates the next character to be read by the Scanner. When we call nextLine() to read the name, it reads the \n as an empty string “”, as if the user simply pressed <Return> when asked for their name! Any other input is left behind on the input stream.

One way to avoid this logic error is simply not to read a String after an int. Often this won’t be practical, so a better solution is to insert the following line after reading the age on line 13:

This will remove the extraneous newline (\n) character from the input stream. We’re not assigning the string it returns to a variable because we know it’s just the empty string “” left on the stream and can be discarded.

Fancy Input

So far, our programs have run entirely within the Dr Java Interactions Pane, but wouldn’t it be snazzy if we could add some pop-up windows to our program?

If you open the Java API and have a look at the JOptionPane class you’ll find that it provides a method called showMessageDialog() that allows you to display a message in a pop-up window, and also a method called showInputDialog() that prompts the user for input, and reads and returns whatever they type as a string. Let’s rewrite the code above using these methods:

We don’t need the Scanner class anymore, but we do need to import the JOptionPane class from a package called javax.swing instead. Swing is a collection of classes that can be used to create any kind of GUI you can imagine. Dr Java itself is written using Swing classes!

Like the methods of the Math class, we don’t need to instantiate a JOptionPane object to use the methods from this class. To call a method we just type JOptionPane. followed by the name of the method we want.

Line 9 calls the showMessageDialog() method.  The first argument is a reference to a parent window (if any) that you’d like to centre your message dialog window on top of.  In this case, we don’t have one so I pass in the null keyword causing the window to be centred in the middle of the screen.  The second parameter is a string containing the message you’d like to display.  You may include escape sequences here, but format specifiers are not allowed.

1-4-InputDialogCool trick, but how about getting user input in one of these pop-up windows?  No problem!  Lines 12 and 14 calls the showInputDialog() method to prompt the user for input and return whatever they type (even if it’s numeric) as a string. For example, if the user types 17 it will be returned as the string “17”.

It’s not possible to cast between a primitive numeric type (int or double) and a String. For example, we can’t do this:

Instead, there are two more Java classes (Integer and Double) that include methods to help us. Both classes are automatically imported as part of the java.lang package. The Integer class includes a method called parseInt() and the Double class includes a method called parseDouble(). These methods take a string as their argument and return the numeric value of it (or a NumberFormatException if the argument contains non-numeric characters). Line 13 demonstrates parseInt() in action.

You try!

    1. Add an entry for “1-4 Getting User Input” in your Learning Journal and answer the following questions:
      1. We’ve now seen 3 different kinds of programming errors: Syntax, Logic, and Run-time. Explain the difference(s) between with a few lines of Java to demonstrate each.
      2. Modify the UserInput3 example so that the final output appears in a GUI message dialog instead of the Dr Java interactions pane; i.e., don’t use print() and println().  Include your solution code in your Learning Journal.