THE Java™ Programming Language, Fourth Edition

(Jeff_L) #1

if (value != null)


processValue(names[i], value);
}
}


Where? on its own is the unbounded wildcard, that can represent any type, "?extendsX" is a bounded
wildcard: It can only represent the type X or any type that extends or implements X (depending on whether X
is a class or interface). This time in processValues we know that, at worst, table.find will return a
Number, so we can store that return value in a variable of type Number.


There is a lot more to generic types and you'll learn about their full power in Chapter 11. Meanwhile, you
know enough about them to understand the simple usages that will occur in the early chapters of this book.


1.14. Exceptions


What do you do when an error occurs in a program? In many languages, error conditions are signaled by
unusual return values like 1. Programmers often don't check for exceptional values because they may assume
that errors "can't happen." On the other hand, adding error detection and recovery to what should be a
straightforward flow of logic can complicate that logic to the point where the normal flow is completely
obscured. An ostensibly simple task such as reading a file into memory might require about seven lines of
code. Error checking and reporting expands this to 40 or more lines. Making normal operation the needle in
your code haystack is undesirable.


Checked exceptions manage error handling. Checked exceptions force you to consider what to do with errors
where they may occur in the code. If a checked exception is not handled, this is noticed at compile time, not at
run time when problems have been compounded because of the unchecked error.


A method that detects an unusual error condition throws an exception. Exceptions can be caught by code
farther back on the calling stackthis invoking code can handle the exception as needed and then continue
executing. Uncaught exceptions result in the termination of the thread of execution, but before it terminates
the thread's UncaughtExceptionHandler is given the opportunity to respond to the exception as best it
canperhaps doing nothing more than reporting that the exception occurred. THReads and
UncaughtExceptionHandlers are discussed in detail in Chapter 14.


An exception is an object, with type, methods, and data. Representing exceptions as objects is useful, because
an exception object can include data, methods, or both to report on or recover from specific kinds of
exceptions. Exception objects are generally derived from the Exception class, which provides a string field
to describe the error. All exceptions must be subclasses of the class Throwable, which is the superclass of
Exception.


The paradigm for using exceptions is the trycatchfinally sequence: you try something; if that something
throws an exception, you catch the exception; and finally you clean up from either the normal code path or the
exception code path, whichever actually happened.


Here is a getdataSet method that returns a set of data read from a file. If the file for the data set cannot be
found or if any other I/O exception occurs, this method throws an exception describing the error. First, we
define a new exception type BadDataSetException to describe such an error. Then we declare that the
method getdataSet tHRows that exception using a throws clause in the method header:


class BadDataSetException extends Exception { }


class MyUtilities {

Free download pdf