Bruce Eckel’s Thinking in Java | Contents | Prev | Next |
contains a class called
Throwable
that describes anything that can be thrown as an exception. There are two
general types of
Throwable
objects (“types of” = “inherited from”). Error
represents compile-time and system errors that you don’t worry about
catching (except in special cases). Exception
is the basic type that can be thrown from any of the standard Java library
class methods and from your methods and run-time accidents.
best way to get an overview of the exceptions is to browse online Java
documentation from
http://java.sun.com.
(Of course, it’s easier to download it first.) It’s worth doing
this once just to get a feel for the various exceptions, but you’ll soon
see that there isn’t anything special between one exception and the next
except for the name. Also, the number of exceptions in Java keeps expanding;
basically it’s pointless to print them in a book. Any new library you get
from a third-party vendor will probably have its own exceptions as well. The
important thing to understand is the concept and what you should do with the
exceptions.
is the basic exception class your program can catch. Other exceptions are
derived from this. The basic idea is that the name of the exception represents
the problem that occurred and the exception name is intended to be relatively
self-explanatory. The exceptions are not all defined in
java.lang;
some are created to support other libraries such as
util,
net,
and
io,
which you can see from their full class names or what they are inherited from.
For example, all IO exceptions are inherited from
java.io.IOException.
The
special case of RuntimeException
first example in this chapter was
== null)
throw new NullPointerException();
can be a bit horrifying to think that you must check for
null
on every handle that is passed into a method (since you can’t know if the
caller has passed you a valid handle). Fortunately, you don’t –
this is part of the standard run-time checking that Java performs for you, and
if any call is made to a null handle, Java will automatically throw a NullPointerException.
So the above bit of code is always superfluous.
a whole group of exception types that are in this category. They’re
always thrown automatically by Java and you don’t need to include them in
your exception specifications. Conveniently enough, they’re all grouped
together by putting them under a single base class called
RuntimeException,
which is a perfect example of inheritance: it establishes a family of types
that have some characteristics and behaviors in common. Also, you never need to
write an exception specification saying that a method might throw a
RuntimeException,
since that’s just assumed. Because they indicate bugs, you virtually
never catch a RuntimeException
– it’s dealt with automatically. If you were forced to check for
RuntimeExceptions
your code could get messy. Even though you don’t typically catch
RuntimeExceptions,
in
your own packages you might choose to throw some of the
RuntimeExceptions.
happens when you don’t catch such exceptions? Since the compiler
doesn’t enforce exception specifications for these, it’s quite
plausible that a
RuntimeException
could percolate all the way out to your
main( )
method
without being caught. To see what happens in this case, try the following
example:
//: NeverCaught.java // Ignoring RuntimeExceptions public class NeverCaught { static void f() { throw new RuntimeException("From f()"); } static void g() { f(); } public static void main(String[] args) { g(); } } ///:~
can already see that a
RuntimeException
(or
anything inherited from it) is a special case, since the compiler doesn’t
require an exception specification for these types.
output is:
java.lang.RuntimeException: From f() at NeverCaught.f(NeverCaught.java:9) at NeverCaught.g(NeverCaught.java:12) at NeverCaught.main(NeverCaught.java:15)
the answer is: If a RuntimeException gets all the way out to
main( )
without being caught,
printStackTrace( )
is called for that exception as the program exits.
in mind that it’s possible to ignore only
RuntimeExceptions
in your coding, since all other handling is carefully enforced by the compiler.
The reasoning is that a
RuntimeException
represents a programming error:
- An
error you cannot catch (receiving a null handle handed to your method by a
client programmer, for example) - An
error that you, as a programmer, should have checked for in your code (such as
ArrayIndexOutOfBoundsException
where you should have paid attention to the size of the array).
can see what a tremendous benefit it is to have exceptions in this case, since
they help in the debugging process.
interesting to notice that you cannot classify Java exception handling as a
single-purpose tool. Yes, it is designed to handle those pesky run-time errors
that will occur because of forces outside your code’s control, but
it’s also essential for certain types of programming bugs that the
compiler cannot detect.