PROPOSAL: Unchecked Exceptions as Subclasses of Checked Exceptions
Derek Foster
vapor1 at teleport.com
Sat Mar 28 17:43:47 PDT 2009
Although I appreciate what you are trying to do with this proposal, and I have certainly been inconvenienced by the problem that you are trying to solve, I am also very concerned with unintended consequences of your proposal. Your proposal describes its intended effect, and it certainly seems able to solve that use case, but does not seem to really delve into other impacts of this change in behavior which might be less positive.
One of the reasons I typically use checked exceptions in programs is to ensure that all callers of an API must consider and handle the various error conditions that can occur. Thus if I have a method like:
void getFoo() throws FooDoesNotExistException;
I can be assured that anyone who calls getFoo() will be forced to consider what to do if the Foo object does not exist. They may choose to ignore the error condition, but at least they will have been forced to consider it (by adding a 'catch' clause somewhere in the program for it or one of its supertypes). This is one of the most important reasons to use checked exceptions in the first place: They allow the compiler to do what amounts to essentially a compile-time proof that all checked exceptions will eventually be handled by someone.
Your proposal seems to have the potential to break this guarantee, so that someone could have a method like:
void getFoo2(); // throws UncheckedSubtypeOfFooDoesNotExistException;
then if I call it in my code:
Foo getStuff() {
return getFoo2();
}
I am never forced to add a catch clause for FooDoesNotExistException anywhere.
Furthermore, I in many ways CAN'T add a catch clause for the base type in outside code, as your proposal suggests is its goal:
Foo getStuff() {
try {
return getFoo2();
} catch (FooDoesNotExistException e) { // This is a compiler error. Exception is never thrown in try block.
// handle exception here
}
}
The only time it would be legal for me to add a catch clause for the base type would be if there was another method also being called in the same try..catch block which DID throw the base exception.
It appears to me that if this proposal is implemented, I will now have the potential for both unchecked and checked exceptions to go entirely uncaught and unhandled in my program, thus invalidating the guarantee that I had (before your proposal) that all checked exceptions would be handled somewhere.
FYI, the workaround that I typically use in your List/File example is to do something like this, which I think of as the "smuggler exception" pattern:
class MyUncheckedIOException extends RuntimeException {
MyUncheckedIOException(IOException cause) {
super(cause);
}
IOException getCause() {
return (IOException)cause;
}
}
// This can't throw IOException, so we have to use the workaround.
File get(int index) {
try {
return _theFile.list()[index];
} catch (IOException e) {
throw new MyUncheckedIOException(e);
}
}
// This knows it is using a List which is backed by Files, so
// it can translate back to a checked exception.
File doGet(List<T> foo) throws IOException {
try {
foo.get();
} catch (MyUncheckedIOException e) {
throw e.getCause();
}
}
Although I would like to have a clean way to throw checked exceptions through interfaces that don't support them (Visitor interfaces are the ones that I personally find most inconvenient in this regard), I am very skeptical that fixing this problem is worth losing the guarantee that all checked exceptions and their subtypes will be handled somewhere.
Derek
-----Original Message-----
>From: Alan Snyder <javalists at cbfiddle.com>
>Sent: Mar 26, 2009 2:57 PM
>To: coin-dev at openjdk.java.net
>Subject: PROPOSAL: Unchecked Exceptions as Subclasses of Checked Exceptions
>
>[This is a revised proposal based on the previous comments. It includes a
>use case.]
>
>Unchecked Exceptions as Subclasses of Checked Exceptions
>
>
>AUTHOR: Alan Snyder
>
>OVERVIEW
>
>FEATURE SUMMARY:
>
>This proposal would allow the definition of an unchecked exception class
>that extends a checked exception class.
>
>MAJOR ADVANTAGE:
>
>Unchecked exception classes are useful when an exception must be thrown
>through an existing interface that does not declare any checked exceptions
>or an appropriate checked exception. If one can define both an unchecked
>exception class and a corresponding checked exception class such that the
>unchecked exception class extends the checked exception class, then the
>unchecked exception will be caught by a try statement that catches the
>checked exception.
>
>MAJOR BENEFIT:
>
>Programs do not have to explictly catch both the unchecked and checked
>exceptions. Most developers need only be aware of the checked exception.
>The potential mistake of not catching the unchecked exception is avoided.
>
>MAJOR DISADVANTAGE:
>
>A new marker interface (or equivalent) must be defined and the definition
>of unchecked exceptions changed.
>
>ALTERNATIVES:
>
>The alternative is to always explicitly catch both the unchecked and
>checked exceptions, which introduces a likely source of programming
>errors.
>
>EXAMPLE:
>
>This proposal uses a marker interface as an alternative way (besides
>subclassing RuntimeException and Error) of indicating that an exception
>class defines an unchecked exception.
>
>The following would define a checked exception and an unchecked exception
>that extends the checked exception:
>
> public class TheCheckedException
> extends Exception {};
>
> public class TheUncheckedException
> extends TheCheckedException
> implements UncheckedException {};
>
>The following is a sketch of a possible use case.
>
>Consider a program A that reads and writes data using file I/O, with the
>presumption that there are good reasons not to read all of the data into
>memory. The program catches IOException in appropriate places so that it
>can recover gracefully should an I/O error occur.
>
>Now suppose that program A wants to use existing library B to manipulate
>this data, but library B does not know about files. Instead, assume that B
>uses some more generic interface to access data, such as List. Note that
>the List get() method does not define a checked exception for data access
>failure. Thus, in the bridge code that allows the file data to be accessed
>via the List interface, program A would have to wrap any IOExceptions in a
>RuntimeException. Suppose it defines a new class, UncheckedIOException,
>for this purpose.
>
>In current Java, program A would need to augment its exception handlers to
>handle both IOException and UncheckedIOException.
>
>Using this proposal, UncheckedIOException could be an unchecked exception
>and also subclass from IOException, so that the exception handlers for
>IOException would catch UncheckedIOException as well.
>
>DETAILS
>
>SPECIFICATION:
>
>The JLS would be changed to add one more way to define an unchecked
>exception.
>
>JLS 11.2
>The unchecked exceptions classes are the class RuntimeException and its
>subclasses, and the class Error and its subclasses. All other exception
>classes are checked exception classes.
>
>would become
>
>The unchecked exceptions classes are the class RuntimeException and its
>subclasses, the class Error and its subclasses, and those subclasses of
>Exception that implement the UncheckedException interface. All other
>exception classes are checked exception classes.
>
>JLS 11.5
>The subclasses of Exception other than RuntimeException are all checked
>exception classes.
>
>would become
>
>The subclasses of Exception other than RuntimeException are checked
>exception classes, unless they implement the UncheckedException interface.
>
>The marker interface UncheckedException would have to be defined in some
>java package, with java.lang being the obvious choice.
>
>COMPILATION:
>
>The compiler would have to be extended to recognize the new category of
>unchecked exceptions.
>
>I'm not aware of other changes.
>
>COMPATIBILITY
>
>The major compatibility issue arises from the introduction of a new name
>in the class name space. That could potentially cause a program to fail to
>compile if it imported a class with the name UncheckedException using a
>wild card import statement.
>
>There could also be programs that examine the class hierarchy at runtime
>or using a compiler API that would not recognize some exception classes as
>being unchecked. I imagine these would mostly be language tools, which one
>would expect to need revision for a new version of Java.
>
>
>
More information about the coin-dev
mailing list