[2520] in java-interest

home help back first fref pref prev next nref lref last post

Re: throws declataration in Java/beta

daemon@ATHENA.MIT.EDU (Jim Graham)
Wed Oct 4 01:04:44 1995

Date: Mon, 2 Oct 1995 14:46:48 -0700
From: flar@bendenweyr.Eng.Sun.COM (Jim Graham)
To: java-interest@java.Eng.Sun.COM, dsmyth@mpfcmd1.jpl.nasa.gov


> > > >Only forseen exceptions are generally required to be declared (and
> > > >therefore need to be caught or explicitly passed on).  Exceptions which
> > > >are subclasses of RuntimeException or Error - which are not generally
> > > >part of the API of a given method - don't have to be declared. 
> 
> Does this mean that all exceptions generated by subclasses should be derived
> from RuntimeException or Error? 

It depends on the API that you are overriding.  If you need to indicate
some kind of programming bug (i.e. equivalent to the caller handing you
a null pointer where you absolutely needed a real object), then throw
something like a NullPointerException, which is a subclass of RuntimeException.
(Or in this case you could just use the pointer and let the runtime throw
the NullPointerException for you).

Cases such as informing the caller about some asynchronous condition
which occured which prevents his *properly formatted* requested action
from being completed - such as a file system running out of space, or a
long wait being interrupted, then hopefully the API that you defined,
or that you are overriding, has been declared to possibly throw an
appropriate exception.  The declaration of this exception is roughly
analogous to declaring a procedure to return a status code instead of
declaring it to return void, except that the exception operates
differently than a return code (i.e. it is thrown and caught rather
than assigned to a variable and tested).

If you are overriding an existing API which did not declare an
exception for you, then this is a problem in the design of that API
similar to what might have happened in C where you are implementing an
API that is defined to return void and suddenly you need to return a
status code - i.e. you are out of luck and the API was defined
inappropriately.  On the other hand, perhaps the person who designed
that API felt that the proper action for the subclass to take when it
finds a problem is to perform some appropriate default action (such as
ignoring the request to delete something which doesn't exist or setting
a value to a default when the requested value is out of range) instead
of bothering the caller with a thrown exception.

> > > >Exceptions such as IOException, which are part of the natural working
> > > >domain of many methods, must be declared where they can occur so that
> > > >callers of that method are aware that the indicated exception is a
> > > >possible result of calling the method. 
> 
> This seems like splitting hairs.  Why isn't an IOException a RuntimeException
> or an Error? 

Because it doesn't represent a programming problem that was detected by
the runtime or an inappropriate use of an API.  It represents useful
information about the operation of a legally specified request that the
caller may have had no control over and that the caller needs to be
informed about - i.e. the filesystem is now full, or the remote end has
closed the connection, or the access priveleges don't allow this action.

> > > It seems to me that this reasoning has a flaw. It assumes that the base
> > > class designer can forsee all possible algorithms needed by all possible
> > > subclasses, and include the necessary exception declarations to cover
> > > them.  
> 
> I also feel this way.  The "subclasses of RuntimeException or Error" seems to
> eliminate this concern, but only because it means that in fact any subclass
> can throw "any" exception, that it invents anyway. 

Any interface can be abused.  If you are defining some kind of general
purpose API that will be implemented by an arbitrary agent, then try to
predict whether or not there will be such agents that may need to indicate
a preventive condition that will be useful for the caller to know about
and plan for the necessary exceptions that these agents may wish to throw.

For instance InputStream is an abstract class, it does not implement a
stream, it merely specifies the API for one.  Since it does not implement
a stream, its read() method doesn't have any exceptions to throw, but
a subclasser may need to throw some kind of exception indicating some
problem with the IO channel which prevents reading.  So, it declares that
it throws IOException.  Now any subclass of InputStream can throw any
flavor of IOException that it wishes - and can even invent its own subclass
of IOException to be distinguishable if such information is useful.

Another example is the toString() method of Object.  It does not
declare any exceptions because it is not useful to have a toString()
method on an object that can throw an exception - the resulting
try/catch insanity on every string construction would be a nightmare.
So, it does not declare any exceptions and callers can rest assured
that they can use it without any dire consequences.  If a subclass
somehow finds a problem in constructing a string representation of
itself it can choose to return an empty string (or even
"myClass[oops]"), or if the problem is something catastrophic such as a
memory failure, then it can throw an OutOfMemoryException (a runtime
exception) or something like that, but callers should not feel as if
there is some reason to doubt the completability of Object.toString()
so no exceptions are declared.

> > Can you give a concrete example?  If a subclasser wants to throw a new kind
> > of exception, then he is most likely trying to fit a round peg into a
> > square hole... 
> 
> OK: ScrollableItemNotFound exception for a derived button to be used in a
> floating "remote control" or palette, which causes the top-most window's
> scrollable item to scroll downwards.   

Why not just define the operation as a Noop if there is no scrollable
item?  On the other hand, since the method from which you return this
would be one that we haven't defined - then you are the one defining
the method, so go ahead and declare it as returning ScrollableItemNotFound.

> It seems that the most useful concept behind exceptions is not that there is
> a fixed set, but that they can be used to handle rare failures, so the code
> is more readable: the "straight" code deals with the nominal case, and the
> "catch" code deals with all sorts of possible exceptions. 

Exactly.  What point are you trying to make here?  We don't have a fixed
set of exceptions, just a predefined contract on each method *we* have
defined in *our* APIs that *we* want to guarantee for people using *our*
APIs.  If you are trying to override one of our methods and you don't like
our choice of exceptions, then perhaps you don't understand the API contract
we have defined, or perhaps you just don't like it, but it is the contract
we wanted.  If you are creating a brand new method, then knock yourself
out allowing "throws Exception" and see how useful it is to try to deal
with that method as a caller.  At some point, you have to drive a stake
in the ground otherwise any method anywhere can throw any exception, even
if the caller did everything he thought he was supposed to do correctly
and the resulting paranoia ends up being useless.

				...jim
-
Note to Sun employees: this is an EXTERNAL mailing list!
Info: send 'help' to java-interest-request@java.sun.com

home help back first fref pref prev next nref lref last post