Skip to content

Programming by Design

If you're not prepared to be wrong, you'll never come up with anything original. – Sir Ken Robinson

  • About
  • Java-PbD
  • C-PbD
  • ASM-PbD
  • Algorithms
  • Other

Chapter 3 – Objects, Input and Output

Posted on June 1, 2019January 7, 2025 By William Jojo
Java Book

(Updated January 7, 2025)

Table of contents

    Objects
    Packages of Predefined Classes and Methods
    Random Numbers – Math.Random()
    (OPTIONAL) Random Numbers – Random Class
    (OPTIONAL) Random Numbers – ThreadLocalRandom Class
    String – Revisited
    VIDEO – Strings
    Output with the printf() method
    Wrapper Classes
    GUI-based I/O
    VIDEO – Basic GUI with JOptionPane
    Converting println to printf
    Quiz
    Exercises

Objects

In the previous chapter, we introduced many things: identifiers, operators, expressions, precedence, and data types. The majority of the time spent was on primitive data types like int, double, char, boolean. We also introduced String, which is not primitive but a class.

Classes are used to describe objects. They define two basic properties:

  1. What they know.
  2. What they can do.

We saw that String variables can have someone’s name assigned to them (what they know), and we could get the length of the contents by invoking a method that counts the characters in the String object (what they can do).

Important Note!
The easiest way to remember the difference between class and object is that a class is a blueprint defining characteristics and details. The object is what does the work – the thing you can touch.

We now begin to continue our journey into Object-Oriented Programming (OOP) by describing what objects are and some terminology surrounding their use. Consider the following:

String s;

s = "My string value.";

The variable s is known as a reference variable. The type String is a class, not a primitive type like int. The reference variable s contains what we will loosely call an address that references the string of characters "My string value." That address is the location of String object. That object is also known as an instance of the String class.

To be more accurate, the above assignment statement is shorthand for the following:

s = new String("My string value.");

In the previous chapter, we saw something similar when introducing the Scanner class. The new reserved word indicates we want to instantiate (create) a String object. This also causes the String() constructor to be invoked. The constructor is responsible for the object’s setup, including setting a specified value. Finally, the address or location of the instance is stored in the variable called s.

To compare primitive data versus objects, see the figure below:

primitive versus object
Figure 1: Storing primitive data compared to storing references.

Consider, again, the following statement:

Scanner kb = new Scanner(System.in);

If we were to read this statement aloud, we would say:

kb is a variable of type Scanner which gets the value of a new Scanner object wrapped around System.in. Similarly, we could say kb is a variable of type Scanner which gets the value of a new Scanner object wrapped around the keyboard.

System.in is pre-defined when your program starts. It is a reference variable that points to an InputStream object. Below is a visual of how kb references the Scanner object that uses the same InputStream object stored in System.in.

kb, Scanner and System.in diagram
Figure 2: Relationship of objects using Scanner to read input from the user.

Since System.in usually represents the keyboard, it is ordinarily just a stream of characters. We can turn a stream of characters into numbers, words, and lines by wrapping that object with a Scanner object.

Similarly, the System.out is predefined and references a PrintStream object. The PrintStream class defines the print(), println() and printf() methods. It also defines many others, but these are the ones we use most.

System.out and PrintStream
Figure 3: The System.out reference to PrintStream.


Packages of Predefined Classes and Methods.

The String class is defined in the package java.lang, which you recall is the package that is automatically imported for our Java programs at runtime.

Java is loaded with predefined classes like the String class. The System class is also predefined. Both String and System come from the predefined package known as java.lang. Packages provide libraries of predefined classes.

These classes also possess predefined methods. You can use any of these classes and their associated methods in your programs as long as you know what package and class to import and the syntax of the methods for a particular class. The following diagram shows a simplified view of package, class, and method relationships. All of these are introduced in this and the previous chapter.

java packages
Figure 4: Packages, classes, and methods.

It is also helpful to know if the methods are static or non-static methods. Simply put, static methods do not require an object for you to use them. You can simply call the method on the class.

In other words, a static method can be called on a class; a non-static method must be called on an instance of a class (object).

Methods often require additional information. This additional information is called the method’s arguments or parameters. These are passed to a method by simply placing the required values into the method’s parentheses. We have already seen quite a bit of this with our output statements. Note, too, that the use of the Scanner class has shown us methods that require no arguments, like nextInt(). Even though the method required no input, we must still provide the parentheses. This is essential to indicate to the compiler that we are invoking a method and not trying to access some unrelated identifier called nextInt.

Important Note!
Although the terms argument and parameter are often used interchangeably, they do have a specific meaning. Parameter refers to the name and type given in the documentation. Argument refers to the value you actually pass to the method when you use it in your program.

The String class consists of primarily non-static methods. Conversely, the Math class is one whose methods are all static. This means we can use all these methods simply using the method’s class name.

The program in Example 1 demonstrates the use of some static methods from the Math class.

Methods.java
import java.util.Scanner;

public class Methods {

    static Scanner kb = new Scanner(System.in);

    public static void main(String[] args) {

        double x, y, square;

        System.out.println("\nThis program uses pow to demonstrate");
        System.out.println("static methods. It will also find");
        System.out.println("the min and max of the two values");
        System.out.println("you have entered.\n");

        // alternate prompting and reading values
        System.out.print("Enter a value for x: ");
        x = kb.nextDouble();

        System.out.print("Enter a value for y: ");
        y = kb.nextDouble();

        // print findings using some Math class methods.
        System.out.println("The value of x raised to the y is " + Math.pow(x,y));
        System.out.println("The min value is " + Math.min(x,y));
        System.out.println("The max value is " + Math.max(x,y));
    }
}

Example 1: Using static methods from the Math class.

A sample run is shown below with user-provided values in bold.

This program uses pow to demonstrate 
static methods. It will also find 
the min and max of the two values 
you have entered. 
Enter a value for x: 3.4
Enter a value for y: 2.7
The value of x raised to the y is 27.226579002152647 
The min value is 2.7 
The max value is 3.4

The Math class contains dozens of methods. Some Math methods are shown in Table 1.

Method Purpose
static double sqrt(double a) Returns the square root of the value in a.
static double cbrt(double a) Returns the cube root of the value in a.
static double pow(double x, double y) Returns x raised to the y power.
static double exp(double a) Return Euler’s number e raised to the a power.
static double random() Returns a positive double value from 0.0 to less than 1.0.

Table 1: Some static methods available to the Math class.

Now that we have introduced one specific method, Math.random(), the following three sections are dedicated to the concept of generating random numbers for a variety of purposes.


In the following three sections, we provide ways to generate random numbers. The learner doesn’t have to know all these methods for generating random numbers. The first section does an excellent job of explaining the details of random numbers, while the following two offer alternatives.

You may proceed with the next section and consider the additional sections optional.


Random Numbers – Math.Random()

When creating games or simulations, there is a strong need for fixed details to help the process to whatever discovery is needed. In addition, we often have to ask a lot of what-if type questions. In other words, rather than using fixed, known quantities, allow the system to operate with a little more entropy or randomness.

From a gaming perspective, the idea of randomness is essential. Imagine a world where random monster encounters are likely to occur. Or perhaps there is only a certain percentage chance that opponents can see each other or a possibility that a magical spell could fail if a monster makes a saving throw.

As a result, we could identify many rules of how encounters can happen but leave it to a dice roll to determine if it will happen. We will begin with a simple 6-sided die roll.

d6 = (int)(Math.random() * 6 + 1);

To understand the above statement, we have to recall the details of the Math.random() method from Table 1. This method returns a value greater than or equal to 0.0 and less than 1.0, but never 1.0. This means that the number can be viewed as representing a portion of something but never the whole something. When viewed this way and we multiply by 6, we are taking a percentage of 6. Recall that Math.random() returns a double, and multiplying by an int does not change the result; it will still be a double.

But, we need an int because die rolls are whole number quantities, so we cast the result to an int. Remember that the cast to (int) on the left happens after the expression on the right. Also, recall that casting to int simply removes the fractional portion, leaving just the whole number quantity.

So, why do we add one? We are adding one simply because we must do it to have the proper range of values. If Math.random() can never return 1.0, we can never achieve a value of 6. The range of whole numbers without adding one is 0-5. When we add one, we add one to both sides of the range, yielding 1-6. Now that is a proper 6-sided die roll.

To develop the details further, consider the following piece of code:

Randomness.java
public class Randomness {

    public static void main(String[] args) {

        double r;

        // get number in the range 0 to <1.0.
        r = Math.random();

        System.out.println("r is " + r + "\n");
        System.out.println(r * 4 + 1);   // 0 -> ~3.9 plus 1
        System.out.println(r * 6 + 1);   // 0 -> ~5.9 plus 1
        System.out.println(r * 8 + 1);   //
        System.out.println(r * 10 + 1);  // ...
        System.out.println(r * 12 + 1);  //
        System.out.println(r * 20 + 1);  // 0 -> ~19.9 plus 1
    }
}

Example 2a: Using Math.random().

This code simulates different dice rolls (d4, d6, d8, d10, d12, and d20) using the same single random value. Some sample output is shown below:

r is 0.10302278380834196

1.4120911352333678
1.6181367028500517
1.8241822704667356
2.0302278380834196
2.2362734057001035
3.060455676166839
r is 0.5935889706585027

3.3743558826340108
4.561533823951017
5.7487117652680215
6.9358897065850265
8.123067647902033
12.871779413170053

In the output produced, the fractional portion was included to show what the value would look like if we did not cast the result. The result would be the whole number quantity upon applying the cast.

Now, let us say that you want to get a random number in a range that is not 0 to something or 1 to something. How about a number in the range of 45 to 92? This can be easily achieved.

Remember that we already know how to get specific ranges. If we want 0-5, we multiply by 6 (see above). If we want 0-9, we multiply by 10. So the generic rule is if we multiply by n, we get the range 0 to n-1. But in the die roll example, we added 1. Yes. Yes, we did. And the secret lies therein – we can add another value to alter the range.

So, 45 to 92 inclusive? No problem. Take a look at the math below.

   45   92
  -45  -45
  ---  ---
    0   47

Since we know how to do ranges that start with 0, we will take the lower bound value and subtract it from both ends of the range. Remember that by adding 1 to the calculation, as we did earlier, we added 1 to both ends. Just make sure that whatever you do, it happens on both ends.

By subtracting 45 from both sides, we get the range 0 to 47. If this represents 0 to n-1, then n is 48. Now we consider:

x = (int)(Math.random() * 48);

However, we must add back what we took away to get us to that zero-based range.

x = (int)(Math.random() * 48 + 45);

Math.random() is not the only method for producing random numbers. Next, we look at the Random class.


(OPTIONAL) Random Numbers – Random Class

The Random class offers several methods to get the job done. However, this class and its methods are not synchronized and, as such, are not thread-safe, which could be a consideration in more advanced projects. The Math.random() method is synchronized and is safer to use where synchronization is required. For our purposes, Random is just fine!

Important Note!
For more information on the purpose of synchronized code, you can read about multi-threaded applications where several parts of a program can be running simultaneously. This is especially important in gaming systems. It is essential to take advantage of multiple cores and CPUs for controller interactions, world updates; creation, interaction, and destruction of video objects; AI; calculating physics.

Table 2 shows some of the components of the Random class.

Method Purpose
Random() Constructor to create a new random number generator.
Random(long seed) Constructor to create a new random number generator with the given seed.
double nextDouble() Returns the next pseudorandom double value from 0.0 to less than 1.0.
int nextInt() Return the next pseudorandom int.
int nextInt(int bound) Return the next pseudorandom int from 0 to less than bound.

Table 2: Some constructors and methods of the Random class.

Now, we look at how to use Random. First, we need to create the pseudo-random number generator object; then, we can produce some random numbers. To use the Random class, we must also import java.util.Random.

TestRandom.java
import java.util.Random;

public class TestRandom {

    public static void main(String[] args) {

        int d6, x;
        Random rnd = new Random();  // create new Random object

        // like Scanner we can use nextDouble() and nextInt()
        System.out.println("rnd.nextDouble() is " + rnd.nextDouble());

        // six-sided die roll.
        d6 = rnd.nextInt(6) + 1;
        System.out.println("d6 is " + d6);

        // uses nextInt(48) to replace (int)(Math.random() * 48)
        x = rnd.nextInt(48) + 45;
        System.out.println("x is " + x);

    }

}

Example 2b: Performing similar tasks with the Random class.

The code in Example 2b will produce different output each time you run it. The result is similar to that shown below.

rnd.nextDouble() is 0.41839914206029805
d6 is 5
x is 72

If you change the line to read

Random rnd = new Random(42);

It will seed the random number generator the same way every time, consistently producing the same random numbers. The output below demonstrates this. Try it and see for yourself.

rnd.nextDouble() is 0.7275636800328681
d6 is 1
x is 65

We are using the same seed, which results in the same set of random numbers based on the mathematical method produced by the method. This is also why we call them pseudo-random.


(OPTIONAL) Random Numbers – ThreadLocalRandom Class

Beginning in Java 7, a new random number generator was introduced. It is thread-safe and very fast. The class is called ThreadLocalRandom, and you need to import java.util.concurrent.ThreadLocalRandom to use it.

Method Purpose
static ThreadLocalRandom current() Returns the ThreadLocalRandom object for the current thread.
double nextDouble() Returns a pseudorandom double value from 0.0 to less than 1.0.
double nextDouble(double bound) Returns a pseudorandom double value from 0.0 to less than bound.
double nextDouble(double origin, double bound) Returns a pseudorandom double value from origin to less than bound.
int nextInt() Returns a pseudorandom int.
int nextInt(int bound) Returns a pseudorandom int from 0 to less than bound.
int nextInt(int origin, int bound) Returns a pseudorandom int from origin to less than bound.

Table 3: Some methods of the ThreadLocalRandom class.

Note that methods of ThreadLocalRandom are similar to those of Random. This is primarily because ThreadLocalRandom is a subclass of Random, meaning it is derived directly from Random. A few new methods were also introduced to include a nextInt() method with lower and upper bounds, allowing us to simplify range-based random number generation.

You cannot create a new ThreadLocalRandom object, which means you also cannot seed it as we could with Random. There is an object associated with each thread of your program. As a result, the proper way to invoke this is:

n = ThreadLocalRandom.current().nextInt(1, 7);

// or

n = ThreadLocalRandom.current().nextInt();

// or

n = ThreadLocalRandom.current().nextDouble();

You may wonder why we need so many ways to generate random numbers. Well, methods, implementation, and speed have improved. The standards also have to consider code that is already in use. This means that the old methods need to be used to support older programs, and new methods are presented with different names. As a result, we end up with several versions.

As mentioned, speed improvements have occurred. The program below compares four methods of generating a six-sided die roll.

  1. The nextInt() method of the Random class.
  2. The nextDouble() method of the Random class (to simulate Math.random()).
  3. The Math.random() method.
  4. The ThreadLocalRandom.current().nextInt() with a specified range.

Each highlighted line in Example 2c corresponds to the above list. Each method is used to generate 100 million random numbers. The time required is measured using System.nanoTime() and converted to milliseconds.

StressRandom.java
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

public class StressRandom {

    /**
     * We test a variety of intense random number generations.
     * nanoTime() is used to measure the realtime cost.
     * The actual time for each is pretty revealing.
     */

    public static void main(String[] args) {

        int x, n;
        long startTime, endTime, timeElapsed;
        Random rnd = new Random();

        /*
            Test 100M random ints on the Random() object.
         */
        startTime = System.nanoTime();
        for (x = 1 ; x <= 100000000 ; x++)
            n = rnd.nextInt(6) + 1;
        endTime = System.nanoTime();
        timeElapsed = endTime - startTime;
        System.out.println("Execution time in milliseconds : " +
                timeElapsed / 1000000);

        /*
            Test 100M random doubles on the Random() object.
         */
        startTime = System.nanoTime();
        for (x = 1 ; x <= 100000000 ; x++)
            n = (int)(rnd.nextDouble() * 6 + 1);
        endTime = System.nanoTime();
        timeElapsed = endTime - startTime;
        System.out.println("Execution time in milliseconds : " +
                timeElapsed / 1000000);

        /*
            Test 100M random ints with Math.random().
         */
        startTime = System.nanoTime();
        for (x = 1 ; x <= 100000000 ; x++)
            n = (int)(Math.random() * 6 + 1);
        endTime = System.nanoTime();
        timeElapsed = endTime - startTime;
        System.out.println("Execution time in milliseconds : " +
                timeElapsed / 1000000);

        /*
            Test 100M random ints on ThreadLocalRandom.
         */
        startTime = System.nanoTime();
        for (x = 1 ; x <= 100000000 ; x++)
            n = ThreadLocalRandom.current().nextInt(1, 7);
        endTime = System.nanoTime();
        timeElapsed = endTime - startTime;
        System.out.println("Execution time in milliseconds : " +
                timeElapsed / 1000000);
    }

}

Example 2c: Stressing random number generators.

The typical timing output is shown below.

Execution time in milliseconds : 1221
Execution time in milliseconds : 2469
Execution time in milliseconds : 2547
Execution time in milliseconds : 368

It is essential to remember that none of this discussion touches on equal spread across the range of values. The reader is left to determine the best way to select a random number generator for a given application.


String – Revisited

The String class needs to have some of its more exciting methods discussed. It has already been stated how important the String class is to Java. Consider the next bit of code:

String s;

s = "My string value.";

/* a few statements later */

s = "A new string value.";

This bit of code demonstrates a very important aspect of Java and object management. The reference variable s contains the instance of "My string value." initially. Then, just a few statements later, it possesses the instance of "A new string value."

Let us consider this very carefully. The assignment operator has the power to instantiate a String object and assign the address to s, which means that for each assignment made, a new object was instantiated. The address of the first was assigned to s, then the address of the second was assigned. So when the second address was set, what happened to the memory for the first instance, and what of the knowledge of its whereabouts?

In the C programming language, we would call this a memory leak – losing track of something resulting from carelessness and, once lost, unable to be reclaimed.

Not so with Java! Java keeps track of every instance of every class and a reference count of the number of reference variables that know an object. When the reference count of an instance reaches zero, the instance is destroyed, and the memory is freed up to be used again. This is known as garbage collection. You can force garbage collection at any time during your program by calling the garbage collector with:

System.gc();

Now for more fun with the String class. Table 4 shows some commonly used String methods.

String Method Purpose
char charAt(int index) Returns the character at index.
int indexOf(char ch) Returns the index of the first occurrence of ch within the string or -1 if not found.
String concat(String str) Returns the string that is this string concatenated with the string value of str.
int length() Return the length of this string.
String substring(int start, int end) Returns the string that is the substring of this string beginning at start until end-1.
String substring(int start) Returns the string that is the substring of this string beginning at start until the end of the string.
String toLowerCase() Returns the string that is this string with all letters set to lower case.
String toUpperCase() Returns the string that is this string with all letter set to upper case.

Table 4: Some common String methods.

StringEx.java
public class StringEx {

    public static void main(String[] args) {

        // set up some String reference vars.
        String s = "The quick brown fox jumps over the lazy dog.";
        String q, d, j;

        // some typical String operations.
        System.out.println("The length of s is " + s.length());
        System.out.println("s.toUpperCase() is " + s.toUpperCase());
        System.out.println("s.toLowerCase() is " + s.toLowerCase());

        // carving up String objects to form other String objects.
        q = s.substring(4, 9);
        d = s.substring(40, 43);
        j = s.substring(20, 25);

        System.out.println(q + " " + d + " " + j + ".");
    }
}

Example 3: Program to demonstrate some String methods.

The code in Example 3 showcases some of these String methods, and the output of a sample run, with user-provided input in bold, is shown below.

The length of s is 44 
s.toUpperCase() is THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG. 
s.toLowerCase() is the quick brown fox jumps over the lazy dog. 
quick dog jumps. 

Knowing details of the String, the substring method is used to pull out the words "quick", "dog" and "jumps"

       0   1   2   3   4   5   6   7   8   9      19  20  21  22  23  24  25      40  41  42  43
     +-------------------------------------------------------------------------------------------+
s -> | T | h | e |   | q | u | i | c | k |   |...|   | j | u | m | p | s |   |...| d | o | g | . |
     +-------------------------------------------------------------------------------------------+


Video showing some basic String operations.


Output with the printf() method

Starting with JDK 5.0, Java offered the printf() method of the standard output object System.out. Those familiar with the printf() function of the C programming language will have no problem adapting to the Java equivalent method. Consider the following example:

final double PI=3.14159;
String s = "My string.";

System.out.printf("Here is the output of our program.%n");
System.out.printf("The value of Pi is %.5f%n", PI);
System.out.printf("The value of s is \"%s\"%n", s);

The printf() method takes as its first argument a string. This string is also known as the format string. Zero or more additional arguments may follow the format string. The format string is essentially a combination of literal text and sequences of placeholders, or format specifiers, that define conversions. The format specifiers are designed to hold a place in the format string, which will be substituted at runtime with a value appropriate to the conversion type.

A format specifier is denoted by the percent (%) sign to indicate that the following sequence of characters describes how the value should be displayed. If a format string contains no format specifiers, then all of the text contained in the format string is processed as if it were a print() method; that is, the cursor remains on the current line and does not move to the beginning of the following line unless an explicit newline (\n or %n) is placed at the end of the format string. A format specifier has the following form:

%[flags][width][.precision]conversion

All of the bracketed values are optional, and their values depend on the conversion selected. Some typical format specifiers are shown in Table 5. One of the nice features of the printf() method is to chop a line into fields of specific sizes to align columnar data. Now, by default, values are right-justified. If the width is wider than the value to be printed, the value will be padded on the left with spaces. If the width is smaller than the value to be displayed, the space will be enlarged to fit the value.

Format Specifier Resultant Output
%-30s Left justified, space padded, string data that occupies 30 character columns.
%c Single character data.
%e Precision floating point data in scientific "e" notation.
%.3f Precision floating point data (float or double) as a decimal value printed to 3 decimal places.
%10d Right justified, space padded, decimal integer that occupies 10 character columns. (No precision)
%03d Zero padded, decimal integer that occupies 3 character columns. (No precision)
%% Percent sign.
%n Platform specific newline.

Table 5: Examples of some simple printf() format specifiers.

PrintfEx.java
public class PrintfEx {

    public static void main(String[] args) {

        String s = "Some string!";
        int x = 32, l;
        double pi = 3.14159;

        // columns from 1 to 30
        System.out.printf("         111111111122222222223%n");
        System.out.printf("123456789012345678901234567890%n");
        System.out.printf("------------------------------%n");

        // decimal integer occupying 10 columns. right then left justified.
        System.out.printf("%10d%n", x);
        System.out.printf("%-10d%n", x);

        // string occupying 30 columns. right then left justified.
        System.out.printf("%30s%n", s);
        System.out.printf("%-30s%n", s);

        // floating point value
        System.out.printf("%f%n", pi);
        // float in 10 columns. 5 for whole number value, one for
        // the decimal point and 4 for the fractional portion.
        System.out.printf("%10.4f%n", pi);
        System.out.printf("%.4f%n", pi);

        l = s.length();
        // strings, ints, and a char.
        System.out.printf("%nThe length of \"%s\" is %d%n", s, l);
        System.out.printf("The last char of \"%s\" is '%c'%n", s, s.charAt(l-1));
    }
}

Example 4: Program demonstrating the use of the printf() method.

The code in Example 4 presents numbered columns. These are used to show where the text is falling about the line. A variety of field widths and left-justify and default justification are demonstrated.

Also shown is a way to use length() to get the last character of the String.

The program in Example 4 produces formatted output shown below.

         111111111122222222223
123456789012345678901234567890
        32
32        
                  Some string!
Some string!                  
3.141590
    3.1416
3.1416

The length of "Some string!" is 12
The last char of "Some string!" is '!'

Wrapper Classes

The wrapper classes are classes that are named similarly to their primitive counterparts. One intent of the wrapper class was to convert from primitives (int, float, char) to objects (Integer, Float, Character) and back again. This can be particularly important in more advanced topics like generics. In Table 6 are listed the Java primitive types and their corresponding wrapper classes.

Primitive type Wrapper Class
int Integer
char Character
short Short
byte Byte
long Long
float Float
double Double
boolean Boolean

Table 6: Primitive type to wrapper class mapping.

It will soon become necessary to convert the string representation of numeric quantities, or numeric strings, into actual integers or doubles. When this happens, you can use the wrapper classes Integer, Float, and Double. These classes contain many static methods, one of which is use for parsing. Parsing is the term for evaluating a sequence of characters and determining if they fit a particular expected pattern. Some examples of wrapper class use are shown in Table 7.

Wrapper Class Method Purpose
Integer.parseInt("12345"); Parses the string "12345" and returns an int whose value is 12345.
Integer.parseInt("10010110", 2); Parses the string "10010110" whose radix (base) is 2 and returns an int whose value is 150.
Integer.parseInt(s); Parses the string s and returns the int value represented by s.
Float.parseFloat("3.14"); Parses the string "3.14" and returns the float value 3.14.
Double.parseDouble("3.1415926"); Parses the string "3.1415926" and returns the double value 3.1415926.
Character.toUpperCase('a'); Upcases the character 'a' and returns the converted value as 'A'

Table 7: Examples using wrapper classes for parsing.

StringsAndChars.java
public class StringsAndChars {

    public static void main(String[] args) {

        //          0123456
        String s = "Abc-128";
        String t = "cHARLIE";
        String name;
        int i;
        char c;

        // Test if char is a letter and determine case
        c = s.charAt(1);
        System.out.println("\nFor the character '" + c + "'");
        System.out.println("Letter: " + Character.isLetter(c));
        System.out.println("Upper : " + Character.isUpperCase(c));
        System.out.println("Lower : " + Character.isLowerCase(c));

        // Test if char is a digit
        c = s.charAt(4);
        System.out.println("\nFor the character '" + c + "'");
        System.out.println("Digit : " + Character.isDigit(c));

        // Change the case of the string.
        c = t.charAt(0);
        name = Character.toUpperCase(c) + t.substring(1).toLowerCase();
        System.out.println("\nName  : " + name);

        // Take substring of s ("128") and convert to an int * 2.
        i = Integer.parseInt(s.substring(4)) * 2;
        System.out.println("\ni is  : " + i);

    }
}

Example 5: Combining some String and wrapper class methods.

The output from Example 5 is shown below.

For the character 'b'
Letter: true
Upper : false
Lower : true

For the character '1'
Digit : true

Name  : Charlie

i is  : 256

GUI-based I/O

On to the fun stuff! No programming class is complete without delving into the Graphical User Interface (GUI). This section introduces two methods of the JOptionPane object. The JOptionPane class may be used in your program by importing the javax.swing package.

The first method of the JOptionPane is showInputDialog() and is intended for user input. This method comes in several flavors with several arguments that could be passed to each version. However, for the sake of introduction, we'll stick to the simplest form, which is demonstrated in the following:

The showInputDialog() method

String name;

name = JOptionPane.showInputDialog("Please enter your name.");

This code declares a string called name, which is used to collect the resulting String object returned by the method. The method prompts the user with the String provided as an argument. The resultant dialog box is shown in Illustration 1.

Show input dialog box
Illustration 1: Result of invoking the showInputDialog() method.

It is important to remember that showInputDialog() returns a String object. This may be obvious since we ask the user for their name, but remember that any use of this method will always return a String object. If you read a numeric quantity from the user, the String object must be converted. This is demonstrated in the next piece of code.

String input;
int age;

input = JOptionPane.showInputDialog("What is your age in years?");
age = Integer.parseInt(input);

The showMessageDialog() method

Output is just as important as reading input from the user when it comes to the GUI. So another method is now introduced called the showMessageDialog() method. This method has several versions, similar to showInputDialog(), and again we will use only one here. The showMessageDialog() method comes in several flavors. The two- and four-argument models are typical, and the general layouts are as follows:

JOptionPane.showMessageDialog(parentComponent, message);

and

JOptionPane.showMessageDialog(parentComponent, message, title, messageType);

The first version does not allow you to provide anything other than a message. You cannot customize the title bar, nor can you choose the type of message graphic.

The parentComponent is an object that represents the parent of the the dialog box. For now, this will be the reserved word, null, indicating that the default component should be used that causes the dialog to appear in the center of the screen.

The message is the body of the dialog and is usually expressed in the form of strings used similar to the println() method.

The title is simply the top line title of the dialog box.

Lastly, the messageType is the category of message being delivered to the user. The options for messageType are shown in Table 5. These values are constants that are defined in the JOptionPane object.

Value of messageType Example
JOptionPane.ERROR_MESSAGE Error Message box.
JOptionPane.INFORMATION_MESSAGE Information message box
JOptionPane.PLAIN_MESSAGE Plain message box
JOptionPane.QUESTION_MESSAGE Question message box
JOptionPane.WARNING_MESSAGE Warning message box

Table 5: Example dialogs for the different messageType values.

Each of the dialog box examples in Table 5 were created with the following statement changing only the value of messageType:

JOptionPane.showMessageDialog(null, "Message", "Title", JOptionPane.ERROR_MESSAGE);

When you have the output that needs specific precision in a dialog box, there is no direct way to process this within the showMessageDialog() method. However, there is a way to prepare the formatted output to be part of the message argument of the dialog box.

The format() static method of the String class offers a way to get the precision you need for your output using a format string similar to the printf() method. The program in Example 6 demonstrates the use of showInputDialog(), format() and the showMessageDialog() methods.

Perimeter.java
import javax.swing.JOptionPane;

public class Perimeter {

    public static void main(String[] args) {

        String input, output;
        double length, width, perimeter;

        // prompt and read length.
        input = JOptionPane.showInputDialog("Length of box:");
        // String needs to be converted to double.
        length = Double.parseDouble(input);

        // repeat for width
        input = JOptionPane.showInputDialog("Width of box");
        width = Double.parseDouble(input);

        // calculation!
        perimeter = 2 * length + 2 * width;

        // build the output as a big String. Note how we cross line
        // boundaries for readability.
        output = String.format("For the box with length %.2f%n", length)
                + String.format("and width %.2f%n", width)
                + String.format("the perimeter is %.2f%n", perimeter);

        // again, crossing line boundaries so we can see each argument passed
        JOptionPane.showMessageDialog(null,
                output,
                "Perimeter of the box.",
                JOptionPane.INFORMATION_MESSAGE);

        System.exit(0);
    }
}

Example 6: Program to demonstrate methods for input, formatting, and output in a GUI.

The dialog boxes produced are as follows. The user entered the values 5 and 12 for length and width, respectively.

Length dialog box

Width dialog box

Perimeter results
Illustration 2: The three dialog boxes of the Perimeter program.

NOTE: Java programs that use the Swing or other GUI components must use the System.exit() method to assure proper termination. An argument value of zero, as shown in Example 6, indicates successful program termination.

The showConfirmDialog() method

There is another way to get information from the end-user. Specifically, the showConfirmDialog() method can help with YES/NO, YES/NO/CANCEL or OK/CANCEL responses.

int buttonPressed;

buttonPressed = JOptionPane.showConfirmDialog(null, "Shall we continue?");

The above is the simplest example of showConfirmDialog(). This displays a simple set of choices: Yes, No and Cancel.

Show confirm dialog box
Illustration 3: Dialog box of showConfirmDialog() method.

The possible set of values returned are shown below.

JOptionPane.YES_OPTION
JOptionPane.NO_OPTION
JOptionPane.CANCEL_OPTION
JOptionPane.OK_OPTION
JOptionPane.CLOSED_OPTION

These equate to constant values defined in the javax.swing package. It is recommended that you always use the name shown above to ensure you have consistent behavior between versions of Java.

Of course, you can select the buttons provided to the user. These are defined as additional constants shown below.

JOptionPane.DEFAULT_OPTION
JOptionPane.YES_NO_OPTION
JOptionPane.YES_NO_CANCEL_OPTION
JOptionPane.OK_CANCEL_OPTION

The DEFAULT_OPTION implies that the Look and Feel should not apply any options. This is useful for giving buttons unique names. These options can be used with the overloaded versions of showConfirmDialog(). One of them is shown below:

showConfirmDialog(Component parentComponent, message, title,
                  optionType, messageType)

This is very similar to showMessageDialog(), but we substitute one the constants for optionType.

int buttonPressed;

buttonPressed = JOptionPane.showConfirmDialog(null,
                        "Your requested changes will be applied.",
                        "Confirming modification",
                        JOptionPane.OK_CANCEL_OPTION,
                        JOptionPane.WARNING_MESSAGE);

The dialog box produced is shown below.

Show confirm dialog box
Illustration 4: More specific version of showConfirmDialog().

The showOptionDialog() method

One more method worth mentioning, without getting too far ahead in the Java language constructs, is the showOptionDialog() method.

This can require arrays and some more complex handling of responses. Consider the following method call:

JOptionPane.showOptionDialog(parentComponent, message, title, optionType,
                 messageType, icon, options, initialValue)

Much like the previous output dialogs, the arguments are well-defined. Although an icon can be provided, we will use null just like the parentComponent. Also, we will provide a list of choices for options and select one of the choices as the initialValue.

Consider a non-traditional response.

Object[] options = { "Baguette", "Chips", "Apple" };
int buttonPressed;

buttonPressed = JOptionPane.showOptionDialog(null,
                 "Which do you like more?", "Wondering...",
                 JOptionPane.DEFAULT_OPTION,
                 JOptionPane.QUESTION_MESSAGE,
                 null, options, options[0]);

System.out.println("buttonPressed = " + buttonPressed);

The return value is the index of the option chosen. This would be 0 for Baguette, 1 for Chips, and 2 for Apple. The code snippet produces the following dialog box.

Show option dialog box
Illustration 5: Using showOptionDialog() for something completely different.



Video demonstrating basic Java GUI with JOptionPane.


Converting println to printf.

This is a brief exercise in translating print() or println() into a printf() method call.

The Premise

Remember that we enjoy a sense of ease of use when writing a println() statement. It is simply, "Print this plus this plus this, then this, and this plus this..."

It's the mental plus that lends itself so easily to writing many println() statements. Effectively, println() has one argument - a big String constructed from all of the parts!

Consider the following taken from various examples:

System.out.println("The value of x raised to the y is " + Math.pow(x,y)); 
System.out.println("The min value is " + Math.min(x,y));
System.out.println("The max value is " + Math.max(x,y));
System.out.println("You have " + guessLimit + " guesses remaining."); 
System.out.println("It's not " + guess +".\n");
System.out.println("\nThe number was " + randomNumber + ".\n");

When converting to printf(), we must remember how this needs to look concerning the argument list. As shown in this link it appears as follows:

public PrintStream format(String format, Object... args)

printf() is a method that takes a format string and zero or more additional Object arguments - separated by commas - to perform the requested output.

Simply stated, printf() wants a format string as the first argument. All subsequent arguments (Object...) are the values to be substituted where the conversions are placed within the format string. This means there are no plus signs mixed in. When you begin the printf() method call, throw plus signs out the window.

The Process

Now, let's get back to the code from above:

System.out.println("The value of x raised to the y is " + Math.pow(x,y)); 
System.out.println("The min value is " + Math.min(x,y));
System.out.println("The max value is " + Math.max(x,y));
System.out.println("You have " + guessLimit + " guesses remaining."); 
System.out.println("It's not " + guess +".\n");
System.out.println("\nThe number was " + randomNumber + ".\n");

First, we determine what the Math methods return, whether it is a double or int.

We need to convert the print() and println() statements to printf(). There is a simple checklist you can follow to convert any println() to printf().

  1. Change println to printf.
  2. Take away all embedded values (variable, constants, method calls, etc.) and, maintaining their order, move them to the end separated by commas.
  3. Substitute conversions (%d, %f, %s, etc) for the values you just removed.
  4. Remove all the extra quotes (") and pluses (+).
  5. Change any \n's to %n and add a %n if converting from println().

An Example

Let's try those steps with the following:

System.out.println("You have " + guessLimit + " guesses remaining.");

Step 1: change println to printf

System.out.printf("You have " + guessLimit + " guesses remaining.");

Step 2: Move the embedded values to the end as comma separated values:

System.out.printf("You have " +  + " guesses remaining.", guessLimit);

Step 3: Substitute conversions for the removed values

System.out.printf("You have " + %d + " guesses remaining.", guessLimit);

Step 4: Remove the extra quotes and pluses.

System.out.printf("You have %d guesses remaining.", guessLimit);

Step 5: Change \n's to %n and add one more if it is println()

System.out.printf("You have %d guesses remaining.%n", guessLimit);

And we are done!

Here are the converted examples from above:

System.out.printf("The value of x raised to the y is %d%n", Math.pow(x,y)); 
System.out.printf("The min value is %d%n", Math.min(x,y));
System.out.printf("The max value is %d%n", Math.max(x,y));
System.out.printf("You have %d guesses remaining.%n", guessLimit); 
System.out.printf("It's not %d.%n", guess);
System.out.printf("%nThe number was %d.%n%n", ramdonNumber);

Quiz

Which of the following will return "pixie"?

String t, s = "Purple pixies aplenty!";
 
 
 
 

Given:

String s = "abcdef123456", t;

Which of the following is a valid substring() method call?

 
 
 
 

You can find the first occurrence of a character in a String using the ______ method.

 
 
 
 

Which of the following produces a random number in the range 30-45, inclusive?

 
 
 
 

The method that is close in syntax to printf() is?

 
 
 
 

What is the result of the following?

String s = "Stargazing for a black hole.";
System.out.println(s.length() + s.indexOf('j'));
 
 
 
 

Which class is comprised primarily of static methods?

 
 
 
 

Which of the following is not a valid Java package?

 
 
 
 

Which of the following produces a random number in the range 1-10, inclusive?

 
 
 
 

Given:

int x = 13;
char c = 'A';
String s = "Mississippi".substring(6,9);

Which of the following will produce the output shown below?

A  13
sip
 
 
 
 

The Swing constant that represents no graphical icon for showMessageDialog() is

 
 
 
 

The System.in reference variable points to which kind of object?

 
 
 
 

Which of the following is a valid printf() method call?

 
 
 
 

From a String you can get the character at a given position using the _______ method.

 
 
 
 

Which of the following format specifier is the best choice for printing a SSN in the form ###-##-####?

 
 
 
 

Which statement will produce the following?

Show input dialog box

 
 
 
 

The System.out reference variable points to which kind of object?

 
 
 
 

The Scanner class is provided by which package?

 
 
 
 

Loading ... Loading …

Question 1 of 18

Loading


Exercises

  1. (Beginner) Which package would you find the following classes:
    1. Scanner
    2. FileReader
    3. String
    4. PrintWriter
    5. JOptionPane
    6. Double
    7. Math
    8. Integer
  2. (Beginner) Which class would you find the following methods:
    1. pow()
    2. charAt()
    3. indexOf()
    4. nextDouble()
    5. random()
    6. showInputDialog()
    7. length()
    8. nextLine()
    9. substring()
    10. printf()
    11. println()
  3. (Intermediate) In your IDE, create some method calls as practice using:
    1. showInputDialog()
    2. showMessageDialog()
    3. showConfirmDialog()
  4. (Intermediate) Write statements using Math.random() for the following ranges:
    1. 2 to 6
    2. 3 to 9
    3. 30 to 55
    4. 59 to 65
  5. (Advanced) Using the indexOf() String method, write statements to determine the location of the bisecting character in the following strings. Then, using substring(), extract the two pieces into separate strings.
    1. Sally Mathers
    2. 3d6
    3. 44*36

Post navigation

❮ Previous Post: Chapter 2 – Elements of the Java Language
Next Post: Chapter 4 – Conditional Control Structures ❯

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Copyright © 2018 – 2025 Programming by Design.