Sample Quiz Answers
For Chapter 9


THIS PAGE CONTAINS SAMPLE ANSWERS to the Quiz on Chapter 9 of this on-line Java textbook. Note that in many cases, there are lots of correct answers to a given question.


Question 1: What does it mean to say that a program is robust?

Answer: A robust program is one that can handle errors and other unexpected conditions in some reasonable way. This means that the program must anticipate possible errors and respond to them if they occur.


Question 2: Why do programming languages require that variables be declared before they are used? What does this have to do with correctness and robustness?

Answer: It's a little inconvenient to have to declare every variable before it is used, but its much safer. If the compiler would accept undeclared variables, then it would also accept misspelled names and treat them as valid variables. This can easily lead to incorrect programs. When variables must be declared, the unintentional creation of a variable is simply impossible, and a whole class of possible bugs is avoided.


Question 3: What is "Double.NaN"?

Answer: Double.NaN is a special value of type double. (It is defined as a public static member variable of the standard class, Double.) It is used to represent the result of an undefined operation on real numbers. For example, if you divide a number of type double by zero, the result will be Double.NaN.


Question 4: What is a precondition? Give an example.

Answer: A precondition is a condition that has to hold at given point in the execution of a program, if the execution of the program is to continue correctly. For example, the statement "x = A[i];" has two preconditions: that A is not null and that 0 <= i < A.length. If either of these preconditions is violated, then the execution of the statement will generate an error.

Also, a precondition of a subroutine is a condition that has to be true when the subroutine is called in order for the subroutine to work correctly.


Question 5: Explain how preconditions can be used as an aid in writing correct programs.

Answer: Suppose that a programmer recognizes a precondition at some point in a program. This is a signal to the programmer that an error might occur if the precondtion is not met. In order to have a correct and robust program, the programmer must deal with the possible error. There are several approaches that the programmer can take. One approach is to use an if statement to test whether the precondition is satisfied. If not, the programmer can take some other action such as printing an error message and terminating the program. Another approach is to use a try statement to catch and respond to the error. This is really just a cleaner way of accomplishing the same thing as the first approach. The best approach, when it is possible, is to ensure that the precondition is satisfied as a result of what has already been done in the program. For example, if the precondition is that x >= 0, and the preceding statement is "x = Math.abs(y);", then we know that the precondition is satisfied, since the absolute value of any number is greater than or equal to zero.


Question 6: Java has a predefined class called Throwable. What does this class represent? Why does it exist?

Answer: The class Throwable represents all possible objects that can be thrown by a throw statement and caught by a catch clause in a try...catch statement. That is, the thrown object must belong to the class Throwable or to one of its (many) subclasses such as Exception and RuntimeException. The object carries information about an exception from the point where the exception occurs to the point where it is caught and handled.


Question 7: Write a subroutine that prints out a 3N+1 sequence starting from a given integer, N. The starting value should be a parameter to the subroutine. If the parameter is less than or equal to zero, throw an IllegalArgumentException. If the number in the sequence becomes too large to be represented as a value of type int, throw an ArithmeticException.

Answer: The problem of large values in a 3N+1 sequence was discussed in Section 1. In that section, it is pointed out that the test "if (N > 2147483646/3)" can be used to test whether the value of N has become too large. This test is used in the following subroutine.

       static void printThreeNSequence(int N) {
             // Print the 3N+1 sequence starting from N.  If N
             // is not greater than 0 or if the value of N exceeds
             // the maximum legal value for ints, than an
             // exception will be thrown.
          if (N < 1) {
             throw new IllegalArgumentException(
                         "Starting value for 3N+1 sequence must be > 0.");
          }
          System.out.println("3N+1 sequence starting from " + N " is: ");
          System.out.println(N);
          while (N > 1) {
             if (N % 2 == 0) {  // N is even.  Divide by 2.
                 N = N / 2;
             }
             else {  // N is odd.  Multiply by 3 and add 1.
                 if (N > 2147483646/3) {
                    throw new ArithmeticError(
                                "Value has exceeded the largest int.");
                 }
                 N = 3 * N + 1;
             }
             System.out.println(N);
          }
       }

(Note that it would be possible to declare that this routine can throw exceptions by adding a "throws" clause to the heading:

        static void printThreeNSequence(int N)
                   throws IllegalArgumentException, ArithmeticException {

However, this is not required since IllegalArgumentExceptions and ArithmeticExceptions do not require mandatory exception handling.)


Question 8: Some classes of exceptions require mandatory exception handling. Explain what this means.

Answer: Subclasses of the class Exception which are not subclasses of RuntimeException require mandatory exception handling. This has two consequences: First, if a subroutine can throw such an exception, then it must declare this fact by adding a throws clause to the subroutine heading. Second, if a routine includes any code that can generate such an exception, then the routine must deal with the exception. It can do this by including the code in a try statement that has a catch clause to handle the exception. Or it can use a throws clause to declare that calling the subroutine might throw the exception.


Question 9: Consider a subroutine processData that has the header

        static void processData() throws IOException

Write a try...catch statement that calls this subroutine and prints an error message if an IOException occurs.

Answer:

        try {
           processData();
        }
        catch (IOException e) {
           System.out.println(
                    "An IOException occurred while precessing the data.");
        }

Question 10: Why should a subroutine throw an exception when it encounters an error? Why not just terminate the program?

Answer: Terminating the program is too drastic, and this tactic certainly doesn't lead to robust programs! It's likely that the subroutine doesn't know what to do with the error, but that doesn't mean that it should abort the whole program. When the subroutine throws an exception, the subroutine is terminated, but the program that called the subroutine still has a chance to catch the exception and handle it. In effect, the subroutine is saying "Alright, I'm giving up. Let's hope someone else can deal with the problem."


[ Chapter Index | Main Index ]