Return to Home Page
      Blog     Consulting     Seminars     Calendar     Books     CD-ROMS     Newsletter     About     FAQ      Search
 

UnCheckedExceptionComments

Please feel free to include corrections to the document as well as comments.


I agree. I write library code that I also use, and I was annoyed by checked exceptions reported by my own code. So I subclassed RuntimeException for the one custom built exception, and used other runtime exceptions already defined in java.lang

The down side is that even runtime exceptions are usefully caught, but you don't find out which ones until runtime. It would be useful if the javac compiler had a flag to set the exception checking level. That way I could see where all the exceptions might be thrown, and catch the ones I'm interested in.

I would also like to retrieve the source code line number of a thrown exception so that I can package it for later diagnosis. It must be available somewhere, because printStackTrace() knows what it is.

Mal.


I can also attest that the following very bad patterns are common in real world Java code:

* The empty exception handler. I just wince when I see this, it is so painful. Yet so many people don't even know why I am wincing. They must have read Bruce's otherwise highly excellent book ;-)

* The exception handler which prints a stack trace then does nothing else, resulting in a program that seems to randomly print a pile of junk to the console as it runs.

* The exception handler which creates a Runtime exception which *only* has the .toString() of the original exception, throwing away the stack trace.

All of these cause unreliable code and / or debugging pain. Many developers (including myself) have taken the same approach as Bruce of having some kind of RuntimeException that wraps another exception. This is far better than the bad approaches listed above.

Like Python, Delphi has good exception handling, but not checked exceptions. I've never had a problem with that. Microsoft left out checked exceptions when designing C#.

So yes, we could definately get by just fine without checked exceptions, and avoid a number of common problems in the process. I think there is some value in knowing that a method you are calling might fail with an IOException, though, so some sort of advisrory-only checked exception mechanism might be an ideal compromise.

Kyle Cordes www.kylecordes.com


I feel that the real objection to Checked Exceptions stems from their misuse. The 'ExceptionAdapter' you use is precisely the mechanism that most exceptions should be handled ... regardless of whether it adapts into a special RuntimeException, or another checked Exception.

It is true that an awkward checked exception scheme can greatly hinder programming efficiency. However, it is also true that it is useful to have the compiler tell you about potential problems you may not have considered when using a class you didn't write. Thus, it is a trade-off. As has already been pointed out, it would be nice if the compiler allowed you to specify one's personal bias.

In the end, I think that your book chapter should advocate 'best practice' for each of Checked and Unchecked exception handling, and not prefer one over the other, because both will be common.

David Bullock dbullock@lisasoft.com


David,

Sorry to disagree with you on this one. I certainly have angst with some parts of exception handling but I don't have any problems with the topic you are discussing.

From my experience, catching an exception happens too soon from inexperienced programmers -- at one time including me. In most cases, almost all exceptions should be 'bubbled up' (by puttings a throws clause in the running method) to the user interface (generally the GUI) that will know how to correctly display to the user what error occurred.

I must confess, checked exceptions help me sleep at night knowing that my code is correct, concise, and fairly clean. I personally prefer a language like Java that helps me enforce rules of good design -- it also prevents project 'runaways'.

The biggest problem with exception handling is the documentation. I have not found any books that teach the 'bubble up' design to help keep code fairly clean and reusable. The problem with the 'bubble up' design is when multithreaded applications have deeply nested concurrently executing threads and the run() method is the highest level of access to a caught exception. Other than this problem, I think checked exceptions are great and will support it's current implementation.

James Moliere

jmoliere@ucsd.edu


> ... like a less precise and provable way of thinking

It *is* a less precise way. That's probably why it's more productive.

> The big advantage Java has over C++ is that exceptions are the only way to report errors."

Only should read "standard" or "usual" or something. A silly C/C++ coder could easily fill your source base with code that returns true/false values or other error codes. A particularly evil programmer could even invent their own errno scheme using a static member! Steven Shaw mailto:steven_shaw@adc.com


This is an interesting discussion and I haven't followed it through to a conclusion for myself yet, however, two things immediately spring to mind:

1) The example appears to show that usage involves a double nest of try clauses. Whilst acknowledgeing the disclaimer given, either the example is bad in that it does reflect correct usage of the ExtendedAdapter (therefore why give it as the sole usage example) or ExtendedAdapter usage appears to lead to more convoluted code than the problem it's trying to solve.

2) When I look at code my standpoint is always "How well can this code be maintained?". Java has a standard methology for handling errors. The article has demonstrated that there are flaws in the process. That leaves two alternatives. Either we go with the standard way (which properly implemented works fine and where improperly implemented can generally be spotted readily (e.g. swallowed exceptions) or we develop an improved alternative which works better and, more importantly, can be maintained more easily by a maintenance programmer coming to the code cold and with no prior knowlege of the logic behind the implementation. I'm not (yet) convinced that double nested try clauses and converting checked exceptions into unchecked ones is the way to go.

Vince O'Sullivan

Code Developer (and Maintainer).


I think another difference between Exceptions and RuntimeExceptions is that un-caught RuntimeExceptions will kill the current thread, unless the uncaughtException() method in ThreadGroup is overridden. This is quite unaccaptable in many cases, which makes RuntimeException less ideal.

Jesper


I do not have the benefit of the Python perspective -- you make me wish I did -- but my first thought is to use AspectJ (www.aspectj.org). That would encapsulate and remove the exception handling code completely from "working" code. Unfortunately the tool is still on the bleeding edge and has a very steep learning curve.

John Allen, john_allen@datacard.com


Much of the extra code written due to exceptions deals with the compiler's insistence that a function which generates or receives a thrown Exception explicitly must handle that Exception unless the declaration of the function also throws the Exception. Sometimes this forces the use of a "throws" declaration in functions that don't really need it.

Perhaps the programmer should be given more control over the situation by small changes in the language and the compiler. How about this:


  public void someFunc() throws checked Exception{ ... }

The modified compiler would report an error if no enclosing code catches the exception. The main() function for any class should contain a try-catch segment to handle any Exceptions generated within the class, and the programmer would be free to decide at which level of the program particular kinds of Exception should be caught.

Jonathan Wilcox, jonathan@menai.com


A brief correction to my prior comment: I meant to say that if the programmer did NOT use the proposed "checked" keyword, the modified compiler would report an error only if no enclosing function catches the exception: if "checked" is used, the compiler would work as it does now.

Jonathan Wilcox, jonathan@menai.com


Because of the number of times that I have burned myself, I never put dummy handlers into code that I am developing. Maybe I'm missing something, but I do allow specific exceptions to bubble up as generic exceptions:

    public static void Inner() throws MyException {
        throw new MyException("Detail", "Extended data");
    }
    
    public static void Outer() throws Exception {
        Inner();
    }

In the example above, I extended Exception and overrode its toString method(). You may catch the generic Exception, or you can catch the specific MyException in the upper reaches of your program. Of course you can use Java's reflectivity to get the original specialized class:


catch (MyException ex) {myexceptionspecificmethod();}

or

/* Not recommended */
catch (Exception ex) {
  if (ex.getClass().isInstance(new MyException())) {
    ((MyException) ex).myexceptionspecificmethod();
}

Given inheritance, could you please elaborate on the advantages of unchecked exceptions and the pitfalls of checked exceptions? I think I must be missing some important concept here. Glen Dayton, dayton@timesten.com


This discussion is thought provoking, although it also is mostly still out of my reach. As a green programmer, when I get an exception my code has failed to produce the desired result. So what an exception looks like to me, as a beginner, is the way that the code died. A messy death would be defined as emptying a whole autopsy to the screen of an unsuspecting customer. I wouldn't want to alarm a customer! However, if I'm debugging, to get the desired function to work, I would want the compiler or runtime to tell me some fairly inteligable stuff about why the code died. Simplistic - yes it is. But if the code runs right and generates exceptions - then the exceptions are false alarms - which tends to be a kind of neurotic pollution. Most of the issue seems to be with, "how to go about learning what can go wrong and ... if there is anything to do." B


Reading that one essay and the discussion made me think - then i did a "grep throws" over all of my code of the past years, i realised how annoying especially all these SQLExceptions, RemoteExceptions and IOExceptions are - and i converted.
Especially these three ones tend to get propagated up a long way - to just a few very well known catching points - and mess up a lot of classes and interfaces on the way.

With interfaces its a particularly bad thing - imagine you defined your business modell as a set of interfaces. EG if your application is backed by a set of flat files you are tempted to declare your methods eg as "throws IOException". But some day you might decide to back your application on XML files, an RDBMS or an RMI server. So what now? replace any "throws IOException" with "throws SQLException"? But what if you want to use the same code at some installation still backed by flat files, on the other one by an RDBMS, yet an other one backed by XML files (SAXException or stuff)? So turn over to an approach like your "ExceptionAdapter". Well, makes your code a bit more ugly again.

So I think in case of infrastructure libs like rdbms / xml / filesystem / network access its desirable to go over to throwing unchecked exceptions.

Another annoying one is the "InterruptedException" thrown by wait()/sleep(). If you just want your thread to wait a little, then you have to write this annyoing empty catch branch. But if you use it in a thread cooperation context, it might be essential to do something in the catch branch. Thats part of the program logic and you see no error handling code at all. Thats all confusing. I dont know how to do better but it seems that InterruptedException is a misuse of the exception system.

So what remains? I do believe in the value of correctness checking at compile time but havent really found an example where Exception checking paid its price in terms of code bloat and messing up your class/interface/library cooperability.

Is there already an RFE for changing this at the Javasoft Bug Parade?

Martin Rust, ru-at-leomedia-dot-org


I would be very surprised if they ever changed it. It's so ingrained in the core of the language, and I'm not sure how many people are questioning it.

However, I don't know of another language that has checked exceptions, and so I've concluded that we've been doing an experiment since Java came out, and some of us are starting to question the success of the experiment.

Bruce


Hi, I think you are a little hard on checked exceptions. I follow Joshua Block's advice in "Effective Java" and get on just fine, in particular:

40: Use checked exceptions for recoverable conditions and run-time exceptions for programming errors
41: Avoid unnecessary use of checked exceptions
47: Don't ignore exceptions

Howard (howard.lovatt@iee.org)


If the problem is exception swallowing, then why not change the compiler to emit a warning whenever it finds an empty exception handler?!

Carsten Kuckuk


Re: the above two comments

Josh's points are certainly standard recommendations for exceptions, as they stand, and probably the best approach for the current language.

The question being posed here is not "what is the best practice for Java exceptions as they exist now" but rather "are checked exceptions a good thing?" In fact, I would argue that Josh's point 41, and Carsten's comment are among the indicators of the problem -- if you need to do these things, could it suggest a fault in the design?

All the feedback that I've gotten so far on other languages continues to indicate that checked exceptions first appeared in Java, and the unofficial story that I heard says that they were slipped into the language while Gosling was on vacation, or a similar tale. This is why I assert that checked exceptions are an experiment, and we are the test subjects. And why I am not (as I once did) simply agreeing that all forms of compile-time checking -- in particular, exception checking -- are a good thing.

Bruce


Bruce,

You have a point. Every new exception that I wrote recently has been a runtime exception, and I usually catch checked exceptions as soon as possible to convert them into runtime exceptions - but I'd never really rationalized this before reading your article.

Still, I suspect that the "throws" keyword is important when it comes to documentation and code readability. "Throws" doesn't just tell the reader that a given method might go wrong, it also tells her *how* exactly it could go wrong. This is important if a method can throw more than one type of exception, and each type of exception can be managed with a different recover strategy. If I'm forced to investigate the various ways that a method can go wrong, I'll probably just ignore the problem (the old assumption that "everything will probably work right"), or I will assume the most generic error ("something went wrong, I don't really care what") and abort the whole operation. The latter is a common approach in languages which don't use exception subtyping - I'm thinking about Basic's "on error gosub".

My argument is that if you decide to do away with checked exception, you'll probably discourage the use of the "throws" keyword, and if you do that you might as well do away with exception subtyping, and just use a single Exception class with a descriptive message. I'm not sure that this would be a tragedy, but it doesn't sound like a good thing either. Maybe I'm overestimating the problem, and learning Python might help me understand it...

--------------
Paolo Perrotta
Bologna, Italy
pperrotta@inwind.it


Note Kevlin Henney's comment on the essay page -- C++, Modula-3 and CLU all have exception specifications that are unchecked, so you can use them to enhance the specification but you're not forced to handle them.

One could argue that if the language doesn't force you to do something like Java's checked exceptions do -- write the handler or pass on the exception -- then people won't do it. But I usually find that trying to force people to behave properly is a fruitless enterprise. In this case, writing handlers that swallow exceptions is a common problem, and it appears that many other people besides myself have come up with the idea of converting checked to unchecked exceptions. I would suggest that the best approach is to provide specificiations, and perhaps a compiler flag to check them if you want. Forcing it has created, in my opinion, code that is more difficult to write read, and thus less manageable, thereby reducing the productivity of the language.

Bruce


Hi Bruce and co,

I've managed to fiddle javac to not check exceptions anymore *evil grin*.

Very simple really. Add a directory java/lang to your project and copy into that directory Exception.java and RuntimeException.java

Change Exception to extend RuntimeException and change RuntimeException to extend Throwable.

Now the compile-time exception checking is turned off.

Heinz

--
Dr. Heinz M. Kabutz (Maximum Solutions)
Author of "The Java(tm) Specialists' Newsletter"
http://www.smotricz.com/kabutz


There's a lot of interesting comments here, and I need to digest some of them more. However, a few things do spring to mind ...
(a) it should be possible to write something that will check compiled code for empty catch blocks - it's just a special case of a decompiler. A tool like that might come in handy in the absence of a 'swallowed exception' warning from javac - and possible more practical, as lazy developers may well just put a useless System.out.println in the catch just to keep the compiler quiet.
(b) re the comment on SQL vs IO vs SAX exceptions, surely the correct way if implementing a general utility for accessing data would be to write a utility specific exception, and encapsulate the SQL/IO/SAX/etc. exception within that. Merely throw'ing the [IO|SQL|SAX]Exception up strikes me as not properly encapsulating the lower levels - the calling code shouldn't have to care what the callee is using at the bottom.

Greg Thomas, Greg.Thomas@iname.com


If you have a copy, check out the Jan 2001 issue of JavaReport. Unfortunately, this is not one of the articles they have made available online ( http://www.javareport.com/html/from_pages/index.asp?mon=1&yr=2001 ), but Todd Lauinger basically makes the same arguments you do, Bruce. Todd emphasizes the fact that RuntimeExceptions help him consolidate his error handling.

The problem with simply using RuntimeExceptions all the time is that some of the specs require the use of checked exceptions (e.g., EJB 2.0 section 18.2.1).

Python's approach sounds interesting, but it appears that I will have to learn to live with both types of exceptions by making sure our developers are fully aware of the issues involved.

Thanks for the thread.

John Crabtree
john@crabtree.com


I've come to very similar conclusions to those in the article. Java mixes the support for two error handling strategies within a single implementation mechanism. The circumstances for using checked exceptions should be closer to those where one would use fallible<> in C++ than where C++ exceptions apply.

There is a discussion of my experience on my website.

Alan Griffiths
alan@octopull.demon.co.uk


I agree with Paolo Perrotta that all exceptions should be run-time but "throws" keyword should be preserved since it is very valuable once you are not the single user of your code. One can go one step further and think of "throws MyException" clause as an attribute of the method (a-la C#).

Kirill Khvenkin
k.khvenkin@worldnet.att.net


Hmmmm

It would seem that the designers of Java regarded error handling as being part of the design of the interface of your class, and thus something that should be enforced.

Java effectively forces you to design error handling into your interfaces up front. It is thus very much a statically-typed language, not at all like the weakly-typed languages like python.

It does however, have it's weaknesses. The addition of chained exceptions in JDK1.4 as least partly addresses this.

Noel Grandin
noel@exinet.co.za


I think Java's exception handling is very broken.

You cannot design exception handling into interfaces: what exceptions can occur at any particular point is a fundamentally dynamic property of the program. You cannot force that to be subject to static declarations. What happens in real Java programs is that some interface doesn't declare some exception, but the code that conforms to it naturally generates it and has to indicate the problem to the caller. Rather than being able to use the obvious, documented exception class, it needs to invent another mechanism. (Generic exception wrappers are the best workaround, and I have been using it myself for years.)

I was curious what people do in real code, so I reviewed quite a bit of exception handling in real-world Java code
(Sun's JDK, various open source projects).

In the best cases, you find something like:

try {
...
} catch(IOException e) {
throw new MyUninformativeException();
}

This is OK, and apparently the intent behind Java exception handling. But it is usually less useful in most cases than letting the original exception bubble up. Exceptions should be caught and handled if the caller knows what to do with it, otherwise, they should be caught and logged by a top-level error handler and recovery routine.

The following occurs with disturbing frequency:

Reader reader = ...;
try {
...
} catch(IOException e)
reader.close();
return ...;
}
reader.close();

Serious bug. Unchecked exceptions may occur inside the
"try" block. try...catch does not protect resources.
That's why try...catch usually isn't useful for ensuring
program robustness. All recovery code must go in
try...finally blocks.

You also see a lot of this thing:

for(;;) {
try {
...
if(...) break;
...
} catch(SomeException e) {
// "do nothing -- cannot happen"
}
}

Well, if it can be thrown, it can happen. And if
it is caught and simply ignored, the code loops
infinitely. There are lots of variants of this.

Overall, Java exceptions don't accomplish what they are
advertised for: with checked exceptions, you still don't
know what can go wrong inside a block of code, you just
know that it won't be reported using the obvious exception.
They are like the Hitchhiker's Guide's panic glasses.

And in an effort to placate the compiler, programmers
add lots of code that makes diagnostics less useful and
often introduces subtle bugs.

Useful, reliable exception handling advice from a compiler
cannot be accomplished by local declarations. If you want a static analysis tool, it has to do whole program analysis. However, most people are better served by simple, robust, well-known exception handling strategies.

It is no surprise that all major programming languages either never got, or dropped, checked exceptions. Even SML, a stickler for static type checking and the language with the best shot at inferring and propagating exception declarations, does not force you to handle exceptions, because it doesn't make sense.

How can this mess be fixed? There is actually a very
simple solution: just make the default exception declaration for methods "throws Exception". That's completely backwards compatible. And that way, people who have gotten attached to exception declarations can continue to use them (and in a few, limited cases, they may indeed be useful), but the rest of us won't suffer from them and the bugs they cause in our code.

Mark Johnson
mj6798 at hotmail.com


I think there is a problem with the code written for

ExceptionAdapter
for demonstration. It is shown bellow:

import java.io.*;
class ExceptionAdapter extends RuntimeException {
  private final String stackTrace;
  public Exception originalException;
...
  public void rethrow() { throw originalException; }

It seems to me that the line above should have been written like this:


  public void rethrow() throws Exception {
     throw originalException;
  }

Now, when it comes to this discussion, I really think that tools that allow you to check for blank exception handlers are really necessary, and the compiler could work as one of these.

The power to make an exception checked or unchecked would be a great flexibility to the language, though it has its own disadvantages. It is a very hard design decision for a language creator and Java is the first one that goes for checked exceptions.

I think that the main problem of this is the way exception handling and detection was implemented. Forcing class writers to subclass Exception and RuntimeException is simply too hard. The use of interfaces and factories to create exceptions would be much more useful and robust.

Possibilities like the one implemented by Bruce, i.e., an Adapter, are attractive and more flexible than the built-in mechanism. If you could make any exception be treated as both checked or unchecked by writing different code would probably be the best solution.

I do think that the lack of an

Exceptionable
interface or something similar and of a
unchecked
keyword or a compiler flag are the real problems. It seems to me that having exceptions checked by default - differently from C/++ and other lggs - would make code more robust - as people would see exceptions by default and would have the possibility to turn them off at any moment.

I am looking forward to reading further comments about these ideas. It is a great discussion!

Michael Nascimento Santos
(m i s t e r _ _ m @ h o t m a i l . c o m)
Software Engineer
Sun Certified Programmer for the Java 2 Platform
SouJava Moderator - www.soujava.org.br
Thinking In Java in Portuguese:
Pensando Em Java (br.egroups.com/group/PensandoEmJava)


I agree with the need to get rid of Checked Exceptions. We have made it a practice on our team to wrap checked exceptions and bubble them up to a point where they can be appropriately handled. The one other issue I think we have with the current approach is that there are so many different exceptions that we have to look for if we let a bunch of unchecked exceptions bubble up. And why do we have to filter through these exceptions based on their class name? Isn’t there a better way to do this? Why is it considered bad practice under normal circumstances to handle an object based on where it falls in the class hierarchy but this is exactly how exception handling is designed to work. Not only do you have to inspect the class name when handling the exception but any time you want to add a new type of exception to handle you create a new class which is identical to all the other exception classes, except for its class name. Would it be better if we added an exception type. The type could be programming error, hardware failure, … This seems like it would make it easier to handle a large number of potential exceptions, you just handle the different types of exceptions rather than every exception class that could have possibly been thrown. It would also be easier to create new exceptions. Just create a new type when you needed it and pass it to an existing Exception class when constructing it.

Justin Meyer
jbmeye00@yahoo.com


Bruce and Heinz,

Bruce, you claim you worked with Heinz on turning Checked Exceptions into Unchecked Exceptions,
but when I look at your example code and the one Heinz wrote at http://www.smotricz.com/kabutz/Issue033.html
I find some differences (besides the class name, that is). You chose to declare the wrapped Exception as public as
well as add a stackTrace variable, whereas Heinz made his Exception private and added the fillInStackTrace() and
getLocalizedMessage() methods.

While it's great you both agree on the need for the class, why the differences in implementation? If this Exception
handling mechanism is recommended, why not agree on a standard way of doing it?! When frequently-read authors
publish something that includes source-code, it gets used by both experienced and inexperienced programmers
all over the world (yes, I'm guilty, too, as charged). We get confused when we see the same thing done several
ways. Are they really the same? If so, which one is best? What tradeoffs, if any, are there?

My last rant is directed at Bruce - it drives me absolutely nuts when anybody shows me something that's
supposed to be great (your ExceptionAdaptor, for example) then proceeds to give an example of how NOT to
use it without providing an example of how to properly use it! ARGH!! Do you have a real-life example?

This discussion sparked my curiosity, so while doing some reading up on Exceptions, I came across the following:

http://javaboutique.internet.com/tutorials/Exceptions/

Do you have any comments regarding the technique described, especially regarding if/whether it should/could be
modified to use ExceptionAdaptor (ExceptionConverter??)?

Thanks for the thought-provoking discussion!


Oops, last post was by Gerry, gerrygiese@mail.com. :-\


Checked or un-checked, exceptions thrown with any of the standard jdk exception classes
provide little solace to the hapless application trying to catch and recover from some
thrown exception. At best a sparse log entry is written and the application either
stops working, works incorrectly or confuses the user. The log entry, I might add, has
only the high level picture of what happened (the name of the exception), where it
happened (the stack trace, and possibly a descriptive string describing it (assuming
the method was kind enough to put a descriptive string argument when the exception
was constructed).

This might be enough, if the descriptive string contains all of the state information
from the objects at the crash site. This is not enough if the intent is to automatically
recover in some fashion from the failure. The caller that is to handle the problem
needs more. Actual access to the state information of the objects interacting at
the point of failure is typically required to gracefully recover. Without this, why the failure
happened cannot be discerned except in the most obvious cases.

I guess what I am trying to say is: use exceptions, checked or unchecked, but supply the
state by subclassing your favorite checked or unchecked exception to include
the objects that were nearby when the method crashed. Fold this in with the
ExceptionAdapter notion and you have a (better) chance at diagnosis of what is wrong.
This is particularly true if the code is running on one of the 50,000 licensed
packages you have sold to your customers. It is certainly less true when the
developer is running the failing application with the debugger. But the point
is: don't you want to sell your application to those 50,000 customers? And when
it fails, heaven forbid, shouldn't it be easy to respond and fix the problem
because you have created an annotated log that fully describes the problem?
(This presupposes that the objects involved in the crash have reasonable
toString() and paramString() methods so that the log can be made.)

Anything less and you are not handling your problems. Producing software
that is robust is hard work. Old country programmers, when they can't fool
themselves into believing they have the "robust", will provide the details to the
crime scene investigator (usually themselves).

Rich Johnson (bouillabaisse at fishpuppy o com)


Exceptions with obligatory checking must die.


I think the points made in [http://java.sun.com/docs/books/tutorial/essential/exceptions/runtime.html]
are valid.
Especially the programmer should be forced to react to failures of "legally specified requests".

Also, all input by the user (or even method parameters that might potentially come from the user, like filenames, or might result from actions from the user, like the number of bytes read from a file) should never result in RunTimeExceptions. Rather those exceptions should be taken care of accordingly (and the programmer should be forced to).

But I also had lots of problems with empty catch blocks.
Maybe the VM should have a flag to exit unconditionally if it meets an empty catch block.

Juergen Weber (juergen at jwi o de)


I think the reason it is hard to come to a conclusion on this subject is because it is conceptually embedded in a more general topic which is "hard" vs. "soft" failure design (programs designed to fail gracefully vs. programs that either work like a Swiss watch or abend), which is an interesting problem. However, on this exact subject, I would say the proof is in the pudding -- I tend to agree with Bruce that experience shows whether a tool is productive or not, for whatever reason. It doesn't do any good to rail against human nature when defending a tool and scold people to be more disciplined. What we need are tools that compensate for human foibles and make us more productive. If, in the long run, experience shows checked exceptions are more burdensome than helpful, that's the way it is and that is who we are as humans -- we need a different tool. Of course, we are not all the same -- checked exceptions may simply be more productive for some people's brains and less for others, which may explain why the debate could go on forever.

But back to the larger picture, which is failure design. I'm sure there is probably a deep body of thinking on the subject, and I haven't studied it formally. But you have to wonder what it means to have errors in a program. Are errors tolerable at all in a program, or do they mean something terribly wrong has happened and it is better to crash the program than let it continue and possible do more expensive damage.

I think there is a fundamental misconception that if you could only understand exceptions, you could handle program failures. Exceptions are the tip of the iceberg. Designing for failure is a mind-bogglingly complicated problem that is simply too overwhelming to do right, unless you throw incredible resources at it, as NASA does.

The problem is, we just don't know what to do if an exception happens unless we dedicate enormous amounts of analysis to the problem. So which is worse for a running program, an empty catch block, or a crashed program? We don't know. One may do more damage, but which?

In the end, I have to think that exceptions are most useful as an extension to the debugging/testing phase of software, which never really ends. Software, unlike a physical system, becomes more robust with age because bugs are continually discovered and weeded out. Exceptions are useful notifications that a bug has surfaced -- all you really need is to be notified where the problem was and as much information as possible about the context. Whether the exception halts or lets the program run is the "soft/hard failure" question that is a whole engineering problem of its own requiring special analysis -- no simple answer in my book.

But what about "expected" exceptions, such as I/O failures and such? If you are expecting the possiblity of a problem at a certain point in your program, then I'd say the best place to deal with it (if you know how) is right there, even though it "junks up" your code. You may also want to deal with it higher up also of course, but then again you will want to deal with it at the point of call, not some off-to-the side exception block. Checked exceptions do provide a useful service of documenting predictable problems you may want to engineer failure recovery for. Of course, return codes also can provide that service -- they just seem out of fashion right now. Return codes are easier to ignore, but empty catch blocks let you ignore checked exceptions.

I guess in conclusion I would have to say:

1. Unchecked exceptions are more useful for finding bugs because programmers won't bury them.

2. It is in general extremely difficult to know what to do if an exception arises, and checked exceptions simply force programmers to write handlers regardless.

3. Checked exceptions provide a useful service in documenting predictable problems. Return codes also provide similar service. Checked exceptions are simply a universal return code object that is forced to be handled or passed back to the calling routine.


Previous comment by Randy Nichols, randynichols@yahoo.com


Checked exceptions are fine: It is just that developers have yet learn how to use them properly. Correct use involves mixing checked and unchecked exceptions appropriately.

A summary of the rules that I have evolved are as follows:

1) Checked exceptions are 'recoverable' exceptions - the part of the 'contract' between the caller and the method is that the caller is given the chance to handle the exceptional condition.

2) Unchecked exceptions are 'unrecoverable'. The method does not expect the immediate caller to be able to handle it and is not offering the opportunity.

3) On rare occations, a recoverable exception 'contract' may exist between a caller and the method that intermediate layers in between are unaware of. This has to be done as an unchecked exception (java.lang.SecurityException is an example of this).

Coming back to point 1 and 2. The implications that stem from these definitions are that Unchecked Exceptions should be used to represent impossible occurrences - those that should never occur in a correctly configured, bug-free system.

Conversely, situations that can occur in a 'correct' system should be thrown as checked exceptions and propagated as such - but only so far as they are regarded as belonging in a 'correct' system - beyond that point they should be wrapped in an unchecked exception.

This usage pattern is similar to that of System and Application Exceptions used in J2EE.

If anyone is interested, I have a decision diagram which tries to cover these options in more detail.

David Hamilton - david.hamilton at jiffle.net


In my experience, exceptions must be handled as an architectural issue - that is, one should handle the exception in the right area of concern. If you employ a layered architecture you would handle db exceptions in the db layer, business exceptions in the business layer and so on (this approach seems to scale well.)

The best approach to handling exception, however, is to handle it as an orthogonal aspect of the rest of the application. While JAspect has been mentioned, languages supporting aspects are emerging (e.g. the Radix language) and these languages will represent a huge step towards a clean solution for handling failures and errors.

Stein Roger (sskaflot@online.no)


I think people who think checked exceptions are a bad idea just don't get it.

First, remember the problem that Checked Exceptions are trying to solve.

How many C/C++ libraries have method calls that return some numeric error code, like

i = someMethodThatReturnsAnErrorCode();

Now honestly, how many often do you check i for an error condition? (Usually 0 or -1)? If you don't, you're the type of person who doesn't like Checked Exceptions. If you do, they you understand Checked Exceptions and you use them.

Even worse, some libraries will set an error flag and you must manually poll this flag after an operation that can cause an error! The API for error checking is not even part of the original method call.

someMethodThatMightSetAnErrorFlag();
flag = getErrorFlag();

Again, if you're the kind of developer that never checks for error conditions, you're not going to like Checked Exceptions.

Robust error checking is part of a well-written application. And Java helps you in this regard by *forcing* you to acknowledge error conditions. When people complain about empty exception handlers, all I have to say is Java can't write error-handling code for you people... that's YOUR job as a programmer. Deal with it.

Now, there are two general kinds of errors that can come up in a running program - improper API usage, like accessing an array element that doesn't exist, and abnormal conditions like a hard disk being full or a file not found, etc. Java provides flexibility in exception handling in this regard. You can throw RuntimeExceptions if a user of your API is passing you invalid data, or has not set up a data structure correctly, etc. These types of errors are *programming errors*, and indicate mistakes in your algorithm. These kinds of errors need to be corrected during debugging of your product. If a production-level application throws a RuntimeException, that's a programming error!

Again, don't blame the language for your lack of error handling code. Blame yourself. Thank the language that it provides a "speed bump" that forces you to acknowledge the called method is reporting an error condition. Then be a grown-up programmer and write the code to deal with the error, or be a lazy programmer and don’t, but don't complain about it, and DEFINATELY don't try to remove a very useful feature from the language. Try learning how to use it correctly instead.

Rob Ross (robross@earthlink.net)


Thank you to Rob Ross for bringing sonme sense to this page.

I can't believe this article or that so many people agree with it.

It is saying... (and if you don't think it is please tell me why)

"Programmer shouldn't be forced to write robust high quality code because it's extra work that they will subversively avoid in order to get the job done. And! on large projects it's too hard to get the code written if the programmers have to handle errors properly. It's better to allow programmers to write lots of poor quality code quickly to meet their development schedules and hope that bugs are caught at some stage in debugging."

I find this is unbelievable. Programmers who'd rather not write exception safe classes with enforced interfaces, complete exception handling, and determinate state, should be fired, just like programmers who don't want to test their code.

C++ (I've been writing it professionally for the last ten years) makes it easy to write so many different types of bugs and not enforcing exception specs is one of the big ones - especially in large distributed projects using CORBA!

I love C# but this is a big oversight. I hope and expect that the CSharp and CLR Teams' reasons for not enforcing exception specification are a lot better than those described in this article.

Baffled,

Nev Delap
Nev.Delap@Australia.Boeing.com


Yes, trapping errors is a pain in the *ss, but isn't that part of the job of developing code? The notion of replacing a compile-time exception with a runtime sounds okay in theory, but what about in practice? Should my word processor crash when I try to open a non-existing file? Which is better, trap an error and either do something intelligent or conscously throw the error back at the caller?

So I guess that means all Windoze developers should just toss that HRESULT out the window also, it's even worse in that field, EVERY d*mned call returns an HRESULT.

I see the real issue as whether you are a developer or a code whacker. Real developers try to trap errors before they crash the program. Code whackers send out crap to users and treat the user as their beta site.

It's called defensive programming. Should you first check that the denominator is a non-zero number before blithely computing its inverse? Heck yes, if you have any sense.

doug


Oops, forgot my email: doug.schwartz@verizon.net


I did not read all of the comments in detail, but if Nev's comments are any indication, I wouldn't have agreed with them much more than the article.

I, too, am amazed that someone (Bruce) who has written so much in support of good design practices would be advocating a viewpoint that checked exceptions are a bad idea. It really does seem as though this article is advocating the idea that forcing programmers to think about error handling is a bad idea because it?takes time? requires extra code?

Quite frankly, one of the biggest problems with software development today is that too many people do not view it as an engineering discipline. What does this mean? Inherent in the idea of engineering is that it is the application of scientific and mathematical principles to solve a problem. These principles are not just basic laws of science and math but are sets of practices that exist to ensure that a product created by an engineer will conform to and perform within a given set of specifications. These statements are true across engineering disciplines--mechanical, chemical, aerospace--but, unfortunately, most programmers do not view their job in this light.

Many programmers today view coding as an art where the solution matters more than the path taken. But this viewpoint is not defensible if software is going to continue to grow as part of our social and economic infrastructure. In order to create a robust infrastructure, the path taken and the practices used matter immensely. After all, would you like to drive your car across a bridge built by someone whose main concern was that it connect two sides of a gap, or a bridge built by an engineer who was concerned that certain practices, error checking, and redundancy were being considered each step of the way? But, all too often, people feel that approach is acceptable with software.

Ignoring engineering when creating software will, inevitably, lead to software that has bugs and that will be difficult to maintain. This costs money; and the more software controls our lives, it could cost far more. Perhaps you might say that, ?For critical systems, good engineering practices can be used, but, for this simple project I'm working on, I don't have to worry about it.? Maybe. But the profession as a whole needs to take engineering to heart, it needs to refuse to accept situations where the user has to restart the program, or, even worse, where a system must be restarted. And the only way this will come about is if engineering practices become *more* ingrained in the languages and tools developers are using, not less.

Checked exceptions are only one facet of good engineering practices. Design patterns are another major facet. And there are others as well (assertions being a good one, "generics" being another I'd like to see). I fully agree that it is often a pain to trap exceptions, but it is so patently wrong to conclude from that that checked exceptions do not belong at the language level. They are a *must* for creating good software where the components declare what errors they might throw, and the users of the components handle those exceptions. Stating that C# does not have checked exceptions despite coming later to the party is not a good argument at all. If anyone thinks that C#'s lack of checked exceptions (or declared exceptions at all!) is going to help create more robust software, they ought to apply for a job at Redmond! C#'s treatment of exceptions is probably its most deficient feature.

In fact, it is a shame that Java did not include a full design-by-contract facility to begin with. Exceptions were there, and they've added some assertion facility, but the software world shouldn't be looking to weaken Java's support for good engineering, it ought to be breaking down the doors to get Sun to strengthen what is already there.

Laziness is no excuse.

Jacy Grannis
jacygrannis@yahoo.com


I don't understand the comment about checked exceptions requiring reams of extra code. If a method is not the correct place a handle a checked exception then it is declared on the throws clause of that method. That is one or at the most two extra words. Hardly a ream.

Often develoeprs are tempted to write extra catch code to avoid adding to the throws clause of a method deep in a large existing body of code because doing so changes the class's interface and that often causes a ripple affect through the call stack. To me this would indicate that the exception handling of the application is not as well designed as it might be.

Steve Palmer (stephen.palmer@step-10.com)
SteP 10
(www.step-10.com)


FYI, Ada 95 HAS an exception system. It's pretty much the same as in Java...

J. Tougas



Hello,

I strongly disagree that checked exceptions are problematic. On the contrary, especially when working in project teams with inexperienced developers, the forced use of exceptions is a big plus.

IMHO, a swallowed exception typically is a programming error or at least bad practice, because even an exception that is swallowed often indicates a condition that at least should be logged on a non-severe log level.


void bar() {
    try {
        foo();
    } catch (Exception e) {
        log.debug("bar - unexpected exception - " + e);
    }
}

I call that "KGB programming". Expect your input data to be corrupted, verify everything, guard against every possibility, and log what happens, especially when things go wrong. Of course, your code becomes "big" and seemingly ugly, but

a) there are coding idioms, namely splitting methods into fine-grained, small submethods, that help with it and

b) the code *needs* to be "big" because it deals with all the non-elegant nitty-gritty rare exceptional conditions that most programmers want to avoid, but which happen in the real world. Many programmers consider only the main variant, implement it, and think they have done their job. But that is not true in a big system that runs for a long time. In a large software system, I think that KGB programming with exceptions is a big help in stabilizing it.

Cheers,
Henrik Klagges
henrik@klagges.com

PS: I read your books since Using C++ / cfront :-)


"FYI, Ada 95 HAS an exception system. It's pretty much the same as in Java...
J. Tougas"

Ada has an exception handling system, but not exception specs - it's an unchecked system. One can define and handle exceptions, but there is no concept of specifying what exceptions a given routine may propagate or must handle. If not handled, an exception is propogated to the top-level of a given thread of control, causing it to terminate.

- Ed


This is a tricky issue. Thanks to everyone for the good debate.

I agree with the latest posters that the problems checked exceptions address must be taken care of in a program sooner or later. IOExceptions rarely happen during testing, but will happen in the field. This makes it a poor strategy to weed them out during testing. I remember this with dread from my C++ days. What other mechanisms could be used?

On the other hand, a lot of bad practices are associated with checked exceptions. When I noticed the empty catch block in Bruce's book, I got really disgusted and decided not to buy it in protest. This is code I see all over the place. I see the following even more frequently:


Socket s = null;
try {
  s = new Socket(...., ...);
} catch ( IOException e ) {
  // logging etc omited
}
InputStream in = s.getInputStream();

The result when the cleaning lady unplugged the network is of course a NullPointerException, masking the true error. Very frustrating. (This is described in Eric Allen's Bug Patterns Column on developerWorks: http://www-106.ibm.com/developerworks/java/library/j-diag3.html)

Here is another argument against checked exceptions: There is no way Java can support true closures. When lamenting over the issues of collection iteration (see Heinz' newsletter for the gory details), I have often dreamed of a Smalltalk/Ruby way of doing it. Sadly, this can never happen. See http://developer.java.sun.com/developer/bugParade/bugs/4280390.html for the gory details (yeah, I am one of the 22 votes for this one)

Lastly, some good news: Java 1.4 introduced the constructor RuntimeException(Exception) which seems to solve the same problem as the ExceptionAdaptor.

Cheers,
Johannes Brodwall - http://brodwall.com/johannes/


ive been using c# for a while now and REALLY miss checked exceptions and execption specifications for 3 reasons.

1. (discussed elsewhere here) inexperienced programmers dont catch things they should. very occasionally occuring conditions arent dealt with because the user doesnt know they exist. particularly true for VB programmers.

2. there is less inclination for the programmer to create their own exceptions because theyre all runtime (i.e. how often in java do you extend runtime exception and how often do you 'throw new RuntimeException("x")')

3. because so much code these days is event driven, systems can easily get out of a valid state if something goes wrong. in other words transactional integrity is often lost. for instance if you parse a string into an integer in java you have to catch it (yes annoying), but in C# you dont. however if there are 5 tasks to do in a method and the exception is thrown during the 3rd then the exception propagates up to the event loop and informs the user who just clicks 'ok'. but the system is now in a fragile state - or is it. how do we know.

i ask anyone who wants to do away with checked exceptions as to how they would program a space shuttle control system without them. would you be sure to look at the documentation of every method you use. would you even trust the documentation was complete?

in c# ive found myself not throwing exceptions where i really ought to because i dont trust the other programmers using my code to read my documentation. for instance i have a windows control that accepts a phone number. it throws certain exceptions if the number is invalid. i found that i had to minimize these because other programmers i was working with didnt ever take the time to catch them so the end user got stuck with the messages.

at the end of the day exception handling just doesnt fit in well with pure object oriented design because an ood system by its very nature interoperates tightly with itself. errors exceptions are basically a spanner in the works. we have to realize (i'm afraid) that there is probably no ideal way to do exceptions, but i maintain that java got it pretty well figured out if safe programming is key. whether or not people abuse javas exception capabilities is not the fault of the language architects, but im still left scratching my head as to why C# has reintroduced the 'virtual' keyword but did away with 'throws'.
-------------------------
java@simonweaver.com


The use of checked exceptions can help with your code, but what takes a while to come to terms with is that you don't have to catch the exception in any code. It's much better to declare that the method throws the exception, and then let a higher-level program deal with it:


public BankAccount {
  private int balance;
  public void withdraw(int amount) throws OverdrawnException {
    if (amount > balance) throw new OverdrawnException(this);
    balance -= amount;
  // ...
}

public class TransferUtility {
  public void transfer(int amount, BankAccount source, BankAccount dest) throws BankAccountException {
    source.withdraw(amount);
    dest.deposit(amount);
  }
}

public class BankAccountException extends Exception {
  private BankAccount account;
  public BankAccountException(BankAccount ba) {
    account = ba;
  }
  public BankAccount getBankAccount() {
    return account;
  }
}
public class OverdrawnException extends BankAccountException {
  public OverdrawnException(BankAccount ba) {
    super(ba);
  }
}

In this example, the 'transfer' method passes any exception up, rather than catching and dealing with any logging. In this example, the exception is propagated up to the caller.

In my experience, the reason why large projects are costly to maintain and/or debug is because programmers use try/catch in the lower-levels writing entries to logs, and then wonder why the app isn't doing what they expect it to.


BankAccount example by Alex Blewitt Alex.Blewitt@ioshq.com


In using C# for several months now I have concluded that I *really* miss checked exceptions. Probably mostly in refactoring when i change my code and want to see which callers need to be changed to catch any new exceptions.
Yes I can rename my method and see what breaks and then catch the exceptions, but I much prefered in Java being able to make the exception checked and find where its used that way.

Anyway - in reading this conversation I've concluded that arguing isnt getting any of us anywhere... and in my case I need to find a solution to handling 'RuntimeExceptions' in C# with no throws clause. If documentation was pristine or there was a throws clause which would tell you which 'RuntimeExceptions' could be thrown things would be a lot better. But there isnt. The biggest problem I see is that someone forgets to catch an exception so it gets propagated up and reported. Great. But whats the point in reporting an error at the top level if it isnt sensibly handled where it occured. In other words, the whole rest of that method is abandoned which may be a very bad thing. Now I cant put try/catch around every statment so I ultimately need to find a good design pattern to help me deal with an absence of both 'throws' and checked exceptions.

-simon
java@simonweaver.com


I'm glad to see a bunch of pro-checked exceptions at last. I was getting pretty discouraged!

I can't really say anything not said already. Exceptions give developers a bit more information on how the code can fail. Proper use of this encourages reuse.

It is all about handling the exceptions at the right level. Again, as someone says, checked exceptions come up too early in a new Java programmer's life, which leads to the design problems mentioned. I'm only just now getting the hang of proper use of the throws clause.

Pat.
patrick forhan


Perhaps I should be a bit more clear: Proper use of the throws clause can help alleviate the try/catch propagation problem and the lazy tactics used to battle it. This might seem a bit backwards...

On another note, as everyone here knows, since Java has both checked and unchecked exceptions, we do have the option of doing things either way. I would call that a feature, I think.

Pat.
patrick forhan


Bruce, I completely agree with you. The first time I began using exceptions was in Borland Delphi. This language use the same exception model as C#.

When I started using Java I got annoyed about the Exception model. The beauty of exceptions is that you manage the "expected" exceptions in the proper place inside your code, and let the "unexpected" exeptions to be catch by a global exception manager or let then uncatched (and the runtime will report them for you).

It is a really annoyance to use the "throws" clause all over your code. It makes exception management almost worthless, because you have to take care of exceptions in every single method. No matter how small and stupid the method is.

For example, I dont want to manage a "Connection Lost" SQLException in every single SELECT statement I do, because this is an uncommon situation. I would like to manage it in a global exception handler, that informs the user about the problem and finish the program. I also don't want to put a "throws SQLException, IOException, etc, etc" in my top level methods.

People that say that an unhandled exception could leave the program in an unstable state, should learn to use "finally" in a proper way.

CheckedExceptions should die

Daniel Mario Vega
dv5a_at_dc_uba_ar


An interested discussion, but it hasn't changed my opinion that checked Exceptions are both *worthwhile* and *necessary*.

All enterprise-quality code should be *known* to work properly, and that means knowing that all expected (application-level) problems are being handled. It's no good adding more exception-handling code as and when you realise you need it, if the first time a particular exception takes down the system, it causes thousands of pounds of lost revenue, hassle for the support staff and an entirely new develop-test-release cycle. Lots of money wasted just because an exceptional condition wasn't being tested for.

There's been the suggestion that you could kick the compiler into a "test" mode to check for uncaught exceptions. For any deeply-nested exception being thrown through multiple interfaces, this will cause masses of output that must be checked against "expected operation" documents etc - do you really expect that developers who can't be bothered to handle an exceptional condition will bother to check this output is correct and expected?

As for the argument that it slows down development, well Java is not a RAD (Rapid Application Development) system - it's a language for writing portable, secure and *correct* code. If you want a RAD system then VB, Perl or Python may be better suited to the job. (I personally use Perl and a bit of VB for my RAD needs.)

Quite frankly, a developer that doesn't write exception-handling code is guilty in my book of gross negligence, and should be let go. Having "not wanted the hassle of writing a few extra lines" is no excuse for having just written code that plain *will not work* in certain circumstance.

Charlie Dobbie
cfmdobbie (at Hotmail)


I think Checked Exceptions in Java are one of the true strengths of Java. It forces a programmer into think about exceptions actively, instead of as an afterthought. I have been doing a lot of Java and C# programming and can say that the quality of the Java code that is produced is much higher than the C# code, and I attribute a lot of this to Check Exceptions.

Justin Kilimnik
justin@pobox.com


Checked Exceptions are really a niceness.
Just bubble them up for conciseness.
Even APIs can be clean,
With CEs handled unseen.
The clarity gained becomes priceless.

Chris Bernard
ChristophBernardAtNetscapeDotNet


The main problem with checked exceptions is that many programmers placate the compiler by swallowing the exceptions with an empty catch block, thereby producing code that is buggier and harder to debug.

I have two possible suggestions:

1- By default, the compiler should issue a warning when a checked exception is not handled.

2- A compiler option allows error reporting for unhandled checked exceptions to be set to off, warning or error.

With a more flexible exception handling mechanism, programmers who are more experienced and more disciplined will continue to produce clean, reliable code. At the same time, programmers who are less experienced and less disciplined will be less tempted to take a shortcut that introduces a bug.

Mazen Mokhtar
mazen@mindcraftinc.com


Contrary to what many posters have asserted, C++ does have checked exceptions. Exception specifications are described in section 14.6 of Stroustrup's "The C++ Programming Language".

In C++, if a method declaration has a throw clause, the definition of the method may throw the types in the throw clause, and no other. The lack of a throw clause indicates that the method throws all types. During runtime, any type being propagated out of the scope of the method, which is not in the throw clause of the method, must be translated by the exception propagation mechanism to a std::unexpected exception.

The fact that C++ programmers have failed to widely adopt the checked exception and my personal experience with using C++ checked exceptions have led me to two conclusions: Most programmers don't see a need for checked exceptions and therefore haven't looked for them; and those who have experimented with checked exceptions find them unwieldy in large scale use.

chas honton
chas@secant.com


Shame on you Bruce and shame on all who agree with you.
Yes checked exceptions are annoying. Like the rule that says you have to put the seatbelt on when you get into your car.
I started coding with C++. Exceptions were those funny things that got written to the console when your application crashed. It meant you had to fix it and nothing else.
After one day using Java, I knew all about exceptions and that’s when I started to write robust code.
Every argument put forward against checked exceptions is a justification for blatantly wrong programming practices. I can’t believe Bruce Eckel has become an apologist for ammeter hackers! The main argument seems to be the prevalence of “swallowed exceptions”.
If an exception is “swallowed” the following are true:
1) The developer is aware that something could go wrong.
2) The developer has made the choice to ignore it.
3) His/Her actions will be blatantly obvious at the next code review.
4) He/She will have no excuses like “I didn’t know the method threw that exception”
The real problem here is an insane stock market and a skills shortage. Too many people writing code who should be librarians. A man with a beard and a funny hat may just have solved this problem. The current economic downturn will weed out the exception swallowers amongst us.

Bing
boingen@yahoo.com


This is a test.


Thrown extra RuntimeException in the case of EJB (or even simple Beans used in a JSP) is not a good idea. Containers take dim view of a RuntimeException, under some circumstances crashing.

There is a better approach: "bubble up" and use a logging scheme (Like the excellent Jakarta's log4J). Include logging in the "Best Practices" for your shop. Beat severely all those that do not follow the rules (if you fire them they'll just do it elsewhere) :-).

If you have a simple consistent error logging framework people will use it since it will be easier than writing their own.

If we remove hard checking from exceptions -- be prepared for lots of ignored exceptions (and no convenient empty catch methods to look for). Water and programmers always follow the path of least resistance.

Even the best of us, will do the least we can (even though we know better). There is never time to write error handling, unless you must.

Nick Rapoport
nrapo@crosswinds.net


I would recast the question this way: "Does Java need subclasses of Exception?"

I agree that swallowing an Exception is unacceptable practice and would never allow it to go through a code review. But I prefer to throw Exceptions up to the layer of my design where I deal with lots of problems, rather than scattering the handlers in many different layers.

Catching one type of Exception in order to throw another type of Exception is something I frequently have to do - but it makes me think that the common denominator in the type tree has been set too far from the root.


Bruce,
I think the discussion you initiated about unchecked exceptions is very nice. Could you please force Zope to provide a time stamp of the message on this forum?
gleb@cornell.edu


I've found checked Exceptions in Java to be less than ideal since either of the following must be done by a calling method.

1 Propagate the exception requiring the interface to be coupled to the implementation (consider changing the implementation, what happens to the exception spec)

2 Wrap the exception but this requires the exception to be handled much the same as a 'C' like return code. Unlike C this can't be ignored as the compiler enforces it, but it contradicts the key purpose of exceptions to separate error handling code from the main bulk, worse still, a try/catch block takes multiple lines whereas "if(p == NULL)" only one ;).

I adopted method 2 in my code as argument 1 is very compelling in my mind. Despite these points I believe checked exceptions are useful in Java. Others have noted that other languages have not adopted this approach, I can only answer in the case of C++. Although C++ has exception specs they seem to be rarely used (throw() aside), this is often not a problem because RAII can allow code to be exception safe without being exception aware. I can write code that completes gracefully independent of which if any exception is thrown. Personally I think this is ideal, it makes code far more local. Java cannot support this idiom, so a method that aquires resources will likely have at least one try/finally block anyway, in light of this handling the specifics of the exceptions as in 2 is little extra burden. That is I believe checked exceptions should remain in Java (not that they could resonably be removed anyway) but are a flawed concept in general.

Another useful observation is as follows. Imagine a well designed exception hierachy for a system. The lower-level/deeper methods of a system will handle very specific tasks and throw very specific errors so subclasses of the hierachy are likely to be thrown, further up tasks are more high level so the exception can be propagated as being of a type nearer the root of the hierachy. This is often overlooked and achieves much the same as wrapping with no burden. For any given library or system that is not too complex, this idiom works on, but it cannot be applied globally since 3rd party libraries will throw exceptions on a different subtree of Exception which will need to be wrapped. Also the exception hierachy starts to dictate how the system should evolve if the idiom is overused. This is not meant as an argument for or against checked exceptions but is a useful pattern for avoiding many of the problems in Java.

Pete
peteralanseymour@hotmail.com


i just completed my first little app in c# and found the unchecked exception system made me very uneasy about where and what could go wrong, as i come from java. and in my java code there are loads if try/catch and never ever, take my word - u may shoot me on sight as i deserve it , an empty catch. i have lead teams here and there and every time i see code with empty or 'weird looking' exception handling it's time for adhoc exception teaching class, that will set everyone straight. someone was lazy, taking shortcuts or just did not know better. so what if the code has 75% error handling and 25% real stuff. thats the way safe code for enterprise systems looks as far as i know. i guess where and when, in what layer etc is debatable but they must be handled properly.

so i made global search on 'c# exceptions' thus finding out bruce has now a another thinking book coming. i'm glad i also found this discussion as i was surprised by all the c# exception links i could read - non of which even touched on the underlying assumption of unchecked vs. checked. very informative to read the pros/cons. i see that even a sold coder like bruce seem to have fallen in the 'snake pit' ;) i would consider myself a mere 'null object' next to b.e in terms coding skill but here it seems i do not agree at all. and coz there are so many pro unchecked voices i ask myself what it is about writing errorhandling that i seem to have not understood. i tend to lean toward the hard school - force them into it, rather than let them get by with no errorhandling if they want to type.

the forum needs a timesstamp on messages btw.

henrik nollkoll@hotmail.com


I don't understand why people are taking polar (opposite) views on this subject. think the real answer is that both checked and unchecked exceptions are very useful. I do use RuntimeException subclasses extensively. Specifically, it's used within the object-relational mapping.

Let me try to solidfy my thinking by asking the following questions:
How do you decide if you need an exception? How do you decide if it should be checked or not?

The answer to the first question is simple (even though some people get it wrong... see below): Use an exception if the normal (sunny day scenario) cannot be followed in a piece of code.

The second question is the real kicker. When I think about an exception, I evaluate the following:

1) How often and under what conditions does this exception get thrown? This question is really crucial. It's really two closely related questions in one, If the conditions are extra ordinary, which also implies rare (for example, a database that holds all the application data not being available), I would go with runtime exception (all see the next question).
2) Can the code that's using this class/method do something about the error? If not, then who can? Can any code whatsoever do something about this, or will a human have to intervene? You have to make this decision when you write the "throw new BlahException()" code, not later. Simply adding the exception to the throws clause just delays this decision. Let's consider the database is down example again. No piece of code can solve that problem. So adding "catch(DatabseIsDownException e)" in a million places will solve nothing. Adding "throws DatabaseIsDownException" to all the methods in the code base will also solve nothing. In my opinion, it's better to make this exception a runtime exception and catch at the top controller level, and report it to the user.
3) Is the exception the sign of a bigger global problem or is it localized to the code that's executing? If it's local, then maybe a local solution is sufficient (i.e., exception should be checked).

Do you have a global mechanism for handling exceptions (don't forget Throwable)? For the code I work with, I do have that: The top level stack is wrapped in a try/catch that redirects to an error page with diagnostic info. It has been invaluable.

Some examples of bad runtime exceptions:
Integer.parseInt() should throw a *checked* ParseException. Since this is usually used in user input handling, it is quite normal for a user to enter crap. An application throwing up when the user puts "asdf" in a numeric field is really not good. Additionally, there is no other way to indicate an error (can't return NaN for an int)

Some examples of bad checked exceptions:
1) EJB's FinderException: This idiotic exception is thrown if the database returns 0 rows. That is not an exceptionary condition. My sql tool certainly doesn't complain when my query returns no rows. It complains if there is a syntax error or if the database is not available. In other words, not only is FinderException bad because it's thrown under normal conditions, but it masks very serious errors that are hard to find, even in testing. The correct implemention would've been an empty collection (after all, that's what the database returned) and a proper exception when something bad happens (Database not available, SQLException , etc).

2) RemoteException: This one fails the second question. I've *never* seen code that can handle a RemoteException, yet everytime you use a remotable object (an EJB, for example), you're supposed to catch this. If you simply ask yourself the question: "what am I supposed to do if the remote server is not responding?", you'll notice that the answer is independent of the piece of code that's trying to execute. This is a problem of a global nature (the same database is down exception). It makes no sense to try to handle it everywhere.

I do agree that whatever exceptions you have, make sure you have the capability to chain a bunch of exceptions together. We've had this in our code for 4 years. It's been added to JDK 1.4 (root cause). It's indispensible. This makes it so you never have to swallow exceptions. It also makes it possible to adhere to interface definitions that are not under your control.

If you look at the comments above, you'll notice that the global vs local handling of exceptions is really a thorny issue. Clearly, current OO systems are not capable of handling this situation properly. New paradigms such as Aspect Oriented Programming try to address this situation and are more likely to be the right solution.

mrezaei at starpoint.com


Hmmm....

A method signature is composed of (more or less):

1) a name
2) a return type
3) a parameter list
4) a throws clause

Rather than just get rid of (4) checked exceptions, why don't we get rid of (2) and (3) as well? Then we would be *really* productive! In fact, why not get rid of strong typing altogether? ;-)

When I'm using a library, I need to know what can go wrong. Without checked exceptions, I'm stuck relying on documentation or code inspection. Even worse, neither the IDE nor the compiler can provide tips about the method's behavior--every time I call it I'll have to recheck my memory.

Alternatively, I could convert everything to a runtime and only provide an application "backstop" to keep the exceptions from crashing the thread. However, by that time I have no idea what are the possible errors or what to do about them. To me, that's a code smell.

I miss checked exceptions in c#.

Design by contract.

Anthony Baker
metatype at anthony-baker dot com


In my opinion one of the major problems mentioned in the article won't go away just by discarding checked exception: Most lazy (or better: undisciplined) programmers who build emtpy catch blocks would also not handle unchecked exceptions correctly (but probably simply ignore them). And unfortunately there's not always a single point where such exceptions can be catched safely.

One question that is not mentioned in the article is: Why have checked exceptions been built into Java? When I started developing in Java several years ago I found exceptions being a great advantage over the languages i worked with before (mainly C and C++) -- because it enforces to care about the errors that may occur and to think about the error handling right from the beginning of design and development. Without it, we had (and still have) all these applications which _silently_ terminate if they encounter an error and leave the user without a clue why this happened.

From my experience in large projects I agree that exceptions can sometimes be annoying - especially if the error handling hasn't been an explicit part of the application architecture and therefore needs to be added or modified in later stages of the project. And I can also follow your arguments for the case that exceptions need to be propagated over large call chains.

But what I don't understand is that the article suggests to revert to the pre-Java scheme of error handling, which basically means programmers may do it or not. Right, this is possible with Java too, but in this case the programmer will always leave a trace in the code (like the empty catch block). Without checked exceptions it's always possible to say "Uh, I didn't know about this one", especially in large projects where it's easy to blame other people for problems.

What would be more helpful from my point of view is a discussion on how the exception handling in Java could be improved in future versions. For example, if unchecked exceptions are to be used for propagating exceptions up the call chain then there should be a mechanism to verify, at latest when testing, that none of these exceptions would cause the application to misbehave or terminate silently. Maybe something like aspect-oriented programming could provide a solution for this.

Elmar Sonnenschein
[contact] [at] [esomail] [de]


aahz@pythoncraft.com

Python is not weakly typed. Python is in fact rather strongly typed;
except for numeric types, there are no automatic coercions or
conversions, and one is not permitted to perform cross-type operations.
What lulls some people into making the "weak type" mistake is Python's
hyper-dynamic polymorphism: many operations use the name of a method,
and if the object provides an appropriately-named method (and an
appropriate parameter list), the object matches the signature required.
This in fact is one of Python's greatest strengths; if you need a
file-like object, you needn't inherit from the file type.


5/30/2003

Checked exceptions and inheritance are two conflicting concepts, I don't think you can support both: your method may throw a IOException, but an overloaded version could make a call to forName() and you have no other choice that swallowing the exception or cart it in a RuntimeException. That's a common thing you face in Swing programming: errors are typically logged at the handler level, I would prefer a global logger inside the Swing main loop.

I think the requirement for java is that any non final method can not make use of checked exceptions.

Loïc Trégan


Please don't call Python "weakly typed" it just perpetuates the myth about dynamically typed languages in general.


It is true that most people don't know what to do with
java exceptions. However, in my opinion this is because
of uproper training. In fact, the exception logic is simple,
effective and very useful when you start migrating or changing code.

The rules are that as soon as you don't know what do do with an exception you propagate it down. And if you know how to handle it you do. If you are sure the exception is
at very sytem level you throw RuntimeException.

There are also O-O rules on how to write proper code.
Example: You have a instance of a class that has config(String fileName) function.
In that case this function should throw IOExeception or
FileNotFound exception back because the one whi geves the file knows why it is missing.

A better O-O solution is to have config(InputStream is)
and avoid the possibility of wrong filename parameter.

It is all about learning O-O thinking


I must confess I disagree with the main point of the article. If you only use unchecked exceptions the temptation is to avoid catching anything, and let unchecked exceptions through. However, by doing this you may miss a really good opportunity to add context to the exception.

In my opinion, it is better to chain exceptions, nesting the caught one in a containing exception. This provides multiple levels of information to the user catching the top-level exception. Sometimes the lowest level exception gives the key clue to the problem's solution, sometime the highest-level exception, and very often an exception somewhere in between.

If I can level one criticism at Java's design, it is that java.lang.Exception (unlike many others: java.rmi.RemoteException, etc..) did not allow a causal exception to be given in it's constructor, enabling exception chaining.


The comment above was added by Malcolm Sparks (malcolm@congreve.com)


jjj


The cause for the exception comes as a parameter to the Exception class constructor in Java 1.4 thus solving the problem of Exception Chaining. I feel climbing up to a higher level is much simpler in case of Checked exception but for certain errors like ResourceNotAvailable runtime exception would be better to handle where the number of levels would be 1

Peter
sowhem@hotmail.com


Hooray! Where has this discussion been all my life?

I can see why people polarise over the issue: I think it's probably experience that's affected us in different ways.

Over the last few years I've come to believe strongly in the use of unchecked exceptions - for pretty much the reasons stated in the initial article. It's great to see it in print.

From the systems I've worked with, I think this: if you stick to unchecked exceptions to throw problems in your system out to your handlers, then the system architecture stands a chance of staying clean. When extra problems arise, the programmer can cleanly deal with them by throwing them out to the central handler(s), without having to modify several method calls along the path. The handler then propagates them out to the UI, which does whatever - pops a dialog, or shuts down or something.

By all means we need checked exceptions between API's - eg it seems absolutely right that the jdbc drivers throw SQLExceptions (which I usually wrap and rethrow as an unchecked exception) - but this shouldn't happen within a single codebase: you just end up with stuff that's painfully hard to modify and maintain in a collaborative environment.

Vivek Iyer
vvi@sanger.ac.uk


I think some of the folks here are not very familiar with the difference between checked exceptions and unchecked exceptions, and exceptions in general.

I haven't seen a single person here advocate getting rid of exceptions in general, getting rid of the throws clause, or ignoring the issue of error handling. Everyone agrees that these are very important and useful things.

The problem with checked exceptions is that they force you to write code to address exception conditions in the wrong place. You might have a high-level error handler that will display a "friendly" error message to the user, log to a database, or otherwise properly deal with the error. You wouldn't want to write dozens or hundreds of lower-level error handlers to do this same task, and you wouldn't want to have to write hundreds of "throws" clauses in your lower-level procedures either.

As someone who writes large amounts of complex java code, including frameworks and APIs, forced exception handling of checked exceptions was such a productivity drain that I spent a week writing a wrapper for jdbc that transformed all the checked exceptions into unchecked subclasses of RuntimeException. And that week spent has paid back in spades with much cleaner, safer code that let error handlers be written in the correct place (usually at the top) without having to propagate endless numbers of throws clauses that have to be created and maintained and added to with every low-level throws clause. JDBC and the IO libraries are the biggest problem APIs, in my experience, but even such calls as Thread.sleep() create an annoying problem. The API wrapping technique works perfectly though (although it does involve a lot of effort). If anyone is interested I'll send my JDK 1.3 version of the wrappers (haven't moved to 1.4 yet).

Matthew Cromer
sdaconsulting@nc.rr.com


Checked exceptions are good in theory, but painful in practice. They lead to write lots of useless statements, that could be easily deduced by the compiler tools.


... and this is a crime.


Hi Bruce!

I agree with you almost. There are only little deficencies of java, where checked exceptions are usual in my opinion. It would be better to improve java and avoid checked exceptions. Here are my rules:

When to use exceptions:

A situation is only exceptional, if the program can not handle it with reasonably effort. Wrong input data should be an expected situation of the regular code, that could be handled gracefully.

The intention of exception-handling is to separate real error-handling from the regular part of the code, so don't force the caller to mix it with unnecessary exceptions.

Only if your code really has a problem to continue e.g., when a parameter is invalid, feel free to throw an exception!

Do NOT throw an exception, if you only suppose the caller of your code could have a problem with a special result. Try to return a special result value instead e.g., null, and let the caller decide with a regular if-else-statement. If the caller really has a problem, HE WILL throw an exception on his own.

But if your code throws an exception, even though it has no real problem and it could continue without an exception and return a special result value, you forestall the decision of the caller, whether the special result is really an error or not.

If you throw an exception, where the caller would decide that it is no error in the context of the caller, you force the caller to write an exception handler in his regular part or to abort i.e., you force the caller to mix regular code with exception handling. That is the opposite of the intentention of exception handling.

Bad example:

java.lang.Class.forName(String) throws ClassNotFoundException

In most programs/situations it is an error if this method does not find the class, therefore it throws an exception and forestalls the decision of the caller. But maybe there is a program that should check a list of class names, whether the classes are present or not. Such a program is forced to mix its regular code with error handling of an exception, that is no error at all in that context. The method should return a special result value instead: null. Many callers of that method have expected that situation and therefore are not in an unexpected situation/exceptional state. They could decide the situation on their own.

Which exceptions to use:

Only throw checked exceptions (not derived from RuntimeException), if the caller has a real chance to handle it. (How many exceptions did you really solve in your life?)

Exceptions that signal programming errors or system failures usually cannot be handled/repaired at runtime -> unchecked exception.

If your code really has a problem to continue e.g., when a parameter is invalid (invalid precondition), throw an unchecked exception (derived from RuntimeException) and do NOT throw a checked exception, because if not even your code can handle the problem, in the very most cases the caller has no chance to handle the problem, too. Instead there maybe somebody somewhere in the highest layers who catches all RuntimeExceptions, logs them and continues the regular service.

Only if it is not possible to return special result values cleanly, use checked exceptions to force the caller to decide the situation. The caller should deescalate the situation by catching and handling one or more checked exceptions, e.g. with special result values(?) or by escalating with an unchecked exception, because the situation is an error, that can not be handled.

Checked exceptions are an official part of the interface, therefore do not propagate checked exceptions from one abstraction layer to another, because usually this would break the lower abstraction. E.g. do not propagate SQLException to another layer, because SQLExceptions are an implementation detail, that may change in the future and such changes should not affect the interfaces and their callers. Instead nest those exceptions into RuntimeExceptions.

exception content:

save all relevant error condition information in the exception:
user, date/time, computer, method parameter values, instance variable values, static/class variable values

I would like to see a better java specification:

1. Allow more than one result of a method:
either named out parameter (caller needs a variable for each parameter)
or anonymous temporary return values (needs a weired syntax?)

This is not needed only to return special values instead of exceptions
it is also needed for other cases where you do not want to
write a special "struct" class for each method and
where you also do not want to return a generic object array
that nobody understands, because it is not documented

2. Good exceptions are Descriptions of exceptional situations at runtime,
they describe what went wrong, e.g. ArrayIndexOutOfBounds and
therefore they describe many implementation details.
Implementation details should not be part of the interface,
because it destroys encapsulation and information hiding.
Therefore do not check exceptions in throw clause and
do not force callers to catch specific exceptions.

Instead if a programmer needs to know wich exceptions are thrown
by one or more methods, he could ask the compiler about that,
and the compiler should always be able to tell him!

3. All exception stack traces should include all method parameter values
of all method calls of the stack trace.
(Aren't they available on the stack of the virtual machine?)

best regards

Thorsten van Ellen

thorsten@textgenerator.com_no_spam


I couldn't agree less.

The purpose of checked exceptions is to give the developer the _opportunity_ to be aware of exceptional conditions. If they chose to do something boneheaded, well, there's only so much a language can do.

If a checked exception gets added to a method, all clients of that method will immediately fail to compile. This is a GOOD thing. It then becomes necessary to consider how the exception should be handled. If the method was unchecked, that consideration (i.e. thought) would be far less likely to occur.

By having checked exceptions, the client code _must_ provide some artifact indicating that the developer spent at least a few seconds thinking about the issue. If another developer comes along later to maintain the code, the first developer's intent is a bit more clear. Even if they simply swallow the exception, the at least the maintenance developer knows that they are dealing with a bonehead. That is, the code exposes their foolishness. This sort of thing is a lot easier to catch in a code review than no code at all.

The approach we have used fairly successfully is similar to ExceptionAdapter, but uses CheckedException. Exceptions are either handled where they are caught, or they are wrapped into an exception type which can be thrown by the method which caught the exception. The advantage of this approach is that you can include information in the wrapping exception which would typically otherwise be lost if it were simply thrown non-stop from the source as an unchecked exception. This can be invaluable when diagnosing a problem.

The basic problem is that people aren't taught how to deal with exceptions.
The rules are simple.
1. Throw an exception if you can't do what you say you are going to do.
2. If client broke the contract of the method, throw an unchecked exception. (e.g. NumberFormatException is an illegal argument thrown by Integer.parseInt(). The client failed on his part of the bargin. If the client knows that he might be failing, then it is his responsibility to deal guard against failure.
3. If the client is not supposed to handle the exception, throw an unchecked exception. These are framework-level exceptions. Document that they should not catch it.
4. Everything else is checked.

If you catch an exception:
1. Handle it, if it is appropriate.
(Typically, if you were the cause.
2. Convert it, following the rules above, if you can't.


I couldn't agree less.

The purpose of checked exceptions is to give the developer the _opportunity_ to be aware of exceptional conditions. If they chose to do something boneheaded, well, there's only so much a language can do.

If a checked exception gets added to a method, all clients of that method will immediately fail to compile. This is a GOOD thing. It then becomes necessary to consider how the exception should be handled. If the method was unchecked, that consideration (i.e. thought) would be far less likely to occur.

By having checked exceptions, the client code _must_ provide some artifact indicating that the developer spent at least a few seconds thinking about the issue. If another developer comes along later to maintain the code, the first developer's intent is a bit more clear. Even if they simply swallow the exception, the at least the maintenance developer knows that they are dealing with a bonehead. That is, the code exposes their foolishness. This sort of thing is a lot easier to catch in a code review than no code at all.

The approach we have used fairly successfully is similar to ExceptionAdapter, but uses CheckedException. Exceptions are either handled where they are caught, or they are wrapped into an exception type which can be thrown by the method which caught the exception. The advantage of this approach is that you can include information in the wrapping exception which would typically otherwise be lost if it were simply thrown non-stop from the source as an unchecked exception. This can be invaluable when diagnosing a problem.

The basic problem is that people aren't taught how to deal with exceptions.
The rules are simple.
1. Throw an exception if you can't do what you say you are going to do.
2. If client broke the contract of the method, throw an unchecked exception. (e.g. NumberFormatException is an illegal argument thrown by Integer.parseInt(). The client failed on his part of the bargin. If the client knows that he might be failing, then it is his responsibility to deal guard against failure.
3. If the client is not supposed to handle the exception, throw an unchecked exception. These are framework-level exceptions. Document that they should not catch it.
4. Everything else is checked.

If you catch an exception:
1. Handle it, if it is appropriate.
(Typically, if you were the cause.
2. Convert it, following the rules above, if you can't.


Hi,
I have been following this discussion for sometime and find it very interesting. As a practising developer with experience in C,C++,and Java I have yet to form an opinion on this topic of exception handling (checked and unchecked).
However I think developers in general must be able to benefit from all the talented folks in this discussion group. To that effect I want to inform you of a new open source project "Open Software Program Coding Standards". The objective of this project is to involve developers and create coding guidelines, standards, best practices, patterns for Java,C,C++,C# and other langauges.
I started this project with the idea that if developers adopt an open standard for coding then it will benefit both the developers and companies. A common coding standard would mean developers won't have to learn variants of coding guidelines in different companies.
Over the next 15 days I will be uploading a presentation outlining the objective of the project.. if anyone is interested in discussing the project and help drive it at various level.. please send me an email at atul.apte@iconexio.com

Sincerely,
Atul Apte
President and CEO
iConexio Technologies.
Administrator
Open Software Program Coding Standards.


IMHO,
Programmer misuse of the checked exception should not be treated as drawback of the checked exception in Java.

I think the java checked exception mechanism could be enhanced by having a :

catchlog(Exception e)

construct in addition to

catch(Exception e)

the proposed catchlog construct would by default log the exception stacktrace and no body is needed. On the other hand the catch construct could be made more robust by adding a compile time check to see that the catch body is not empty.

Example:

[case a]: "I don't want the interference of the checked
exception "ServiceException" thrown by method "doSomething()" of class "ServiceProvider" in my code"
//-- code 1 --//
try {
serviceProvider.doSomething();
} catchlog(ServiceException se); //note this requires no body
//-- end code 1 --//

[case b]: "I want to do some error recovery"

//-- code 2 --//
try {
serviceProvider.doSomething();
} catch(ServiceException se) { // do some error recovery
doErrorRecovery(se);
}
//-- end code 2 --//

The advantage of this is that if I leave the catch block in case b empty and continue to use the "catch" construct instead of "catchlog", the compiler will complain.

I understand that by enforcing this simple
change in newer versions of Java some of the existing code may break (when there exist empty catch block).
One suggestion for incorporating this in the newer JDK version without breaking the codes written for previous versions is that the compiler signal a warning instead of error in case the above specified contract is violated.

~ Amol Deshmukh
Graduate Student,
Electrical and Computer Engineering and Computer Science Dept.,
University of Cincinnati


What a great discussion.

I agree with the Bruce's observations. It's true that "the programmers should know better," but unfortunately, we don't always (or usually) have that control. I participate in lots of code reviews, and even though I'd *like* people to be more knowledgeable, the fact is that people frequently and often swallow checked exceptions. These problems aren't all found during inspections, and even if they are, the developer often says "thanks for pointing that out, I'll fix it after the meeting." Will the code actually be fixed? Do we need yet another review meeting? The situation is worse for out-sourced components. Until experience proves otherwise, my advice will be "Be selective about the use of checked exceptions, then make sure those cases are carefully reviewed. Using checked exceptions following their philosophical intent, as advised by sources such as "Code Complete," may be well-intentioned but problematic because of the unreliability of programmers to use them appropriately."

Max Rahder
Java Mentor and Trainer
max@rahder.com


I feel that the real objection to Checked Exceptions stems from their misuse. (David Bullock)

I have not found any books that teach the 'bubble up' design to help keep code fairly clean and reusable. (James Moliere)

This discussion shows that checked exceptions have at least one benefit: they force developers to think about error handling. Or maybe not, because developers can still choose to ignore the issue by writing empty handlers or throwing RuntimeExceptions. In almost every project where I worked, I tried to initiate a discussion about error handling - usually without success. It is a fact of life that developers prefer not to think about what can go wrong. Maybe the biggest mistake of the Java designers was to believe that the compiler can force developers to change bad habits.

I think the literature must share the blame. Even excellent Java books like Bruce's often ignore the issue or even give bad advice. What is needed, besides rules of good practice, are nontrivial text book examples of how to do it right.

I remember how I was annoyed about the empty handlers in (I think) the 2nd TiJ edition. And while I appreciate the discussion Bruce has initiated, I have the impression that there is some rationalization in his change of view. If the point is that checked exceptions encourage bad developers to write even more bad code (swallow exceptions), hey, there are many ways to write bad code. I don't think it helps if you tell those developers it's all Java's fault. By the way, I have seen silly exception handling in C++, too.

Toni


Sorry for singling out somebody but the remarks by Thorsten van Ellen really need to be corrected. However, it's a good bad example because it shows how exceptions can be misunderstood.

1. "A situation is only exceptional, if the program can not handle it with reasonably effort. Wrong input data should be an expected situation of the regular code, that could be handled gracefully. (...) Only if your code really has a problem to continue e.g., when a parameter is invalid, feel free to throw an exception!" So what's the difference between "wrong input data" and "invalid parameter"? Any input data will eventually end up as a parameter of some method and if it's wrong, the method can't fulfill its contract. But it can't ask the user to retype the input either, that's the GUI's duty. So if the GUI doesn't immediately check the validity of the input, it must be told about it by an exception, which it can then handle gracefully. Another point, if "real" exceptions by definition can't be handled, what good it is to throw them? They will have to be handled at some point. The method where the exception occurs can't know how it will be handled and it needn't know how it will affect the client.

2. "Do NOT throw an exception, if you only suppose the caller of your code could have a problem with a special result. Try to return a special result value instead e.g., null, and let the caller decide with a regular if-else-statement." That is really the worst you can do. A method doesn't, and needn't, know anything about the caller. All it needs to know is its own contract. If it can't fulfill it, it's an exception. The client can expect to be returned a meaningful value of the specified type without having to check for 0 or null (horror!) every time. 0 and -1 are meaningful integer values and not error conditions. An empty collection is a valid object. null is not. Returning null will almost always results in a NullPointerException. Never even think of it!


(above comment again by Toni)


(There are few exception to the above rule, like Map.get(). In some cases, null must be considered as a valid object value and not as exceptional. But those rare cases should be intuitively clear by looking at the signature, otherwise you risk NulPointerExceptions.)


Hi Toni!

I think your answer to mine is reasonable. I think I understand it and
nevertheless I find it not to be a contradiction to my rules.
Of course, I did not write a whole article in this discussion and
therefore some rules are not really complete.
But perhaps I can shortly answer some of the "contradictions":

Where to catch exception?
Of course you want/need to catch exceptions,
if your system should continue service(s).
The missing rule here is: do it mostly on the top calling level and
don't do the whole work all the way up and
mess up your interface and
show all the implementation details behind your interface and
break all the abstraction layers e.g,
with a low level SQLException at your high-level struts-action.

Wrong input Hi Toni!

I think your answer to mine is reasonable. I think I understand it and
nevertheless I find it not to be a contradiction to my rules.
Of course, I did not write a whole article in this discussion and
therefore some rules are not really complete.
But perhaps I can shortly answer some of the "contradictions":

Where to catch exception?
Of course you want/need to catch exceptions,
if your system should continue service(s).
The missing rule here is: do it mostly on the top calling level and
don't do the whole work all the way up and
mess up your interface and
show all the implementation details behind your interface and
break all the abstraction layers e.g,
with a low level SQLException at your high-level struts-action.

Wrong input


Something went wrong with last submission, here is the remaining part:

Wrong input Something went wrong with last submission, here is the remaining part:

Wrong input


Wrong input vs invalid parameter?
Wrong input is a special case of invalid parameter.
I only want to give one example when it is useful to differentiate between them:
In case of errors (exceptions) I want to log all the exceptions at top level
to be able to locate and analyse it at any time.
But I do not want to log every wrong user input and
spam my log file with 99% of uninteresting wrong user input.
If I would log every wrong user input,
I could analyse typical wrong user input,
but it is hard to find all the other more interesting exceptions,
that indicate a real bug in my code, that I want to fix.

But even if all I said above is true, you may be right,
to handle wrong input as exception, because the contract is not fulfilled.
So another rule should be:
at least let the caller differentiate wrong input from other Exceptions!
Even a batch job may want to react different to wrong file input
than to programming error such as ClassCastException.
In the case of wrong file input, the batch may want to log the errornous record number
and jump to the next record.
In the case of a programming error the batch may want to stop at all.

I agree with you:
> The client can expect to be returned a meaningful value of the specified type
> without having to check for 0 or null (horror!) every time.
The special result value was meant in conjunction with the bad example:
null would be a example for java.lang.Class.forName(String classname)
as meaningful as an empty collection for some kind of a search method.
By the way, I think you agree, that meaningful values can be part of the contract.

best regards

Thorsten van Ellen

thorsten@textgenerator.com_no_spam


Wrong input vs invalid parameter?
Wrong input is a special case of invalid parameter.
I only want to give one example when it is useful to differentiate between them:
In case of errors (exceptions) I want to log all the exceptions at top level
to be able to locate and analyse it at any time.
But I do not want to log every wrong user input and
spam my log file with 99% of uninteresting wrong user input.
If I would log every wrong user input,
I could analyse typical wrong user input,
but it is hard to find all the other more interesting exceptions,
that indicate a real bug in my code, that I want to fix.

But even if all I said above is true, you may be right,
to handle wrong input as exception, because the contract is not fulfilled.
So another rule should be:
at least let the caller differentiate wrong input from other Exceptions!
Even a batch job may want to react different to wrong file input
than to programming error such as ClassCastException.
In the case of wrong file input, the batch may want to log the errornous record number
and jump to the next record.
In the case of a programming error the batch may want to stop at all.

I agree with you:
> The client can expect to be returned a meaningful value of the specified type
> without having to check for 0 or null (horror!) every time.
The special result value was meant in conjunction with the bad example:
null would be a example for java.lang.Class.forName(String classname)
as meaningful as an empty collection for some kind of a search method.
By the way, I think you agree, that meaningful values can be part of the contract.

best regards

Thorsten van Ellen

thorsten@textgenerator.com_no_spam


I have noticed a truly alarming trend in on-line articles that are beginning to suggest that the Java community rely more heavily on unchecked exceptions. I have seen more than one article actually recommend that checked exceptions be converted to unchecked exceptions.

I tend to have the opposite opinion - unchecked exceptions are the evil that should be avoided. Allow me to explain.

The Java language provides a very clear example of the purpose of unchecked exceptions - most of the standard unchecked exceptions are for programming errors like illegal arguments, array violations and invalid state. Why is this the case? Simply because unchecked exceptions do not enforce any handling as they are invisible in the API and programmers have no way of knowing that they will be thrown.

Thus, an unchecked exception will usually percolate up through the various code layers until it brings down the JVM. Maybe this is a perfectly acceptable outcome for a programming error, but certainly not for a condition that the programmers expected to happen as a well-defined failure path.

Consider that

NullPointerException
is a typical unchecked exception. Quite honestly, this is the last thing that I would expect to have to check for if I was using well-written code. If I were to pay for a library that throws this exception, I would throw that library back into the abyss from which it came. Why? Because it's indicative of bad code as are all of the standard unchecked exceptions.

The main argument in favor of moving more heavily towards unchecked exceptions appears to be that programmers will be "annoyed" by checked exceptions and just swallow them. I find it odd that the same people who complain that programmers will swallow checked exceptions have no problem believing that those same programmers will be willing to code for "invisible" unchecked exceptions.

The problem that the community appears to have, although it has not come up in this context yet, is that programmers only code for success paths and never deal with failure paths. This is not unique to the Java community. I have coded in C, C++ and Java and I have found that the habits are the same, regardless of language.

Exceptional conditions are part of a the API. Checked exceptions force a recognition of this fact. They impose the failure path upon the programmer and I see this as a good thing. The only "bad" thing about it is that programmers continue to be sloppy and we, as a community, should be actively training them to be MORE responsible, not less so.

My advice on best practices would be the following:

1. Declare all parameter violations as

IllegalArgumentException

2. Never allow a
NullPointerException
to be generated by code that you wrote
3. Never allow a
ClassCastException
to be generated by code that you wrote
4. Preserve encapsulation by catching lower level errors and throwing an exception defined as part of your API. Keep in mind that there might be multiple lower-level exceptions that all result in the same exception to be thrown within your API. The point is to report on YOUR code's failure condition, not the lower-level condition. Lower level conditions are meant to be reported as "root cause" because they are supposed to be anecdotal by the time your code has finished processing them.
5. Declare a different checked exception for each unique failure condition as well as one parent exception that is a super class for them all. Consider the well-known
IOException
which is a parent to many different sub-conditions. Well-written code can choose to catch the specific lower-level condition - like
FileNotFoundException
- or it can just catch the parent. One rule of thumb for the creation of checked exceptions is "one exception for each unique error message presented to the user".
6. Preserve lower-level messages for accurate logging. Only provide a custom message if you are the originating point of an exception. If you are wrapping-and-throwing, take the message from the cause and use it for the wrapping exceptions message:
throw new BlahException(original.getMessage(), original)

7. In the rare occasion that an exception should be swallowed by a mid-level layer of code, the event MUST be properly logged as a warning. If you believe you should log an error instead, then either the exception should never have been swallowed in the first place or the design needs revision.
8. The highest level of client code should catch all declared exceptions and log them before taking further action.
9. The highest level of client code should employ a catch clause for
RuntimeException
to ensure that all unchecked exceptions are dealt with to prevent trashing the JVM.
10. Anticipate I18n requirements. Unique checked exceptions allows programmers to map exceptions to message resources. Alternatively, a base exception could allow an message key to be specified, providing the UI with a way to map an exception to a specific message. As an example, a badly formatted data stream could throw a
BadFormatException
and include a key code that provides the necessary detail for the benefit of the UI.

Sorry for the length of this comment. I didn't intend to be quite so verbose.

Jonathan Ginter
jginter@yahoo.com


I totally agree with Jonathon Ginter. I think unchecked exceptions are in general evil.

IMHO, the Java language should have simply divided problems into "exception" and "error".

NullPointerException should, IMHO, be an error. Similar for IllegalArgumentException. They're quite literally programming errors, so why not name them as such?

Programming errors should not require error catching code (or everything would have to check for NPE...). You *can* catch them, but don't need to, as they shouldn't happen unless the programmer screws up.

All true exceptions should be caught. These are things that describe conditions that are not programming mistakes or environmental blowups (like out of memory).

I see Bruce's main points (and counter them) as:
1) Coders get annoyed and swallow exceptions
-- This is what code reviews and checkstyle are for!

2) Code gets cluttered
-- Our job is to tell people how to write good error
handling so the code isn't cluttered, it's full of
robustness

3) Interfaces get bound to technology
-- See comments below

Many programmers write interfaces like

public void getAccounts() throws SQLException;

This is just plain bad design. The interface should be used to separate implementation details from object communication. If the interface doesn't need to talk about a specific technology, it shouldn't. If it does, like the above, changes in underlying technology for interface changes. Evil.

A key point that Jonathon mentions, your API should define exceptions that it wants to propagate. For example, if you're writing a banking application that deals with Accounts, you could define

public void withdraw(int accountId, double amount)
throws AccountNotFoundException,
InsufficientFundsException,
AccountAccessException;

These are *logical* exceptions.

Any *technological* exceptions (like SQLException, EJBException or IOException) are wrapped appropriately as *logical* exceptions.

If we get a technological exception that basically means "not found", we throw an AccountNotFoundException.

If we get "connection failed", we throw AccountAccessException.

The caller decides if it can handle the problem. Not found could likely be handled, while access exception means "something bad happened and you likely can't do anything, but at least you know the bad thing that happened". Access exceptions would likely be presented to the user/log with a "please contact tech support" message.

This removes the argument about interfaces being tied to technology.

Of course the real problem is that everything that everyone on this issue states is "gut feel". There have been no studies to prove or disprove anything.

The "success" that people have with just using unchecked exceptions could be genuine, or it could be that they're lucky that the rest of the code and the environment is solid (or that errors are ocurring and they don't know it...)

later,
- Scott Stanchfield
scott@javadude.com


Background on Checked and Unchecked Exceptions
The idea behind checking an exception is that the compiler checks at compile-time that the exception is properly being caught in a try-catch block.
You can identify checked and unchecked exceptions as follows.

Unchecked exceptions are the classes RuntimeException, Error and their subclasses.
All other exception subclasses are checked exceptions.
Note that whether an exception is checked or unchecked is not defined by whether it is included in a throws clause.

From http://java.sun.com/j2se/javadoc/writingdoccomments/#throwstag
==================================
So in my opinion the Compiler should just report errors for empty catch blocks


It seems to me there are two leading "correct" approaches to exception handling. One is the model where I wrap the SQL/SAX/IOException with an AintNoDataException and maybe wrap it again as it goes higher up the call stack. The other is to propagate it as an unchecked exception.

Either way, what usually happens is that it's an autopsy report. It unwinds to the top of the stack or very nearly there and results in a message saying "sorry dude, try again next year" and a big stack dump in the log.

In this case, is it really worth the effort of tracking how it propagates through the system, wrapping and rewrapping it nicer packages only to unceremoniously explode it at the end? Although I see the elegance in these reports, usually there's enough log context already that the exception wrappers aren't adding anything. I tend to look straight to the bottom of the trace for the original cause. I don't see the bubble-up approach being worthwhile for the effort alone, much less the risk of mishandling along the way.

What about the other case, where we actually attempt to recover from the error? It's theoretically attractive, but rare in practice. This almost always requires some interaction with the user and that is usually not available deep in the code. So we end up unwinding to the top anyway.

Now, once we're there, which helps the user more: an OperationFailedException which wraps a BlowedUpException which wraps a FileNotFoundException, OR... the FileNotFoundException itself? There are other ways for recovery to happen, but in my experience, nine times out of ten wrapping exceptions makes recovery harder, not easier.

What about the other times? Well, just because exceptions are unchecked doesn't mean they can't be handled. In most cases, handling should happen in a "finally" block, not a "catch" block anyway, and if anything checked exceptions tend to distract us from that rather than reminding us.

If necessary, though, "catch" works just as well on unchecked exceptions as it does on checked exceptions. Your class is no more robust by forcing your callers to do "something" about it if there's really nothing they can do, or if they don't know what it is. We've all seen the forms that "something" will take.

Scott at Vachalek dot org


Regarding: http://www.mindview.net/Etc/Discussions/CheckedExceptions (by Bruce Eckel, the guy who wrote Thinking in Java)

Interesting reading. In some part I agree with the distinguished gentlemen, however, they seem to have made one serious mistake: they allow a class to throw unspecified exceptions, but then expect clients of the class to code how to interpret the various types of exceptions thrown.

The whole point is that in good OOAD interfaces are specified clearly, and clients can only interact with an object according to its interface. If the interface does not list a particular exception, then it is meaningless to try to catch the exception. Doing so couples the specification with the implementation, and will fail when we refactor the implementation, and for no good reason.

I believe best practice remains to "throws" exactly the exceptions a class plans to throw in the normal scheme of things (as compared to exceptions rising from bad code or a crashed mainframe, neither of which should be planned for in the normal scheme of things). If an object A uses a service B, and the interface for B throws Exception E, but the interface for A does not, then the E has to be wrapped or otherwise handled. This is consistent with Martin Fowlers discussion on the use of Exceptions (in Refactoring: Improving the Design of Existing Code, at my desk), and James Goslings views (http://www.artima.com/intv/solid.html), both of which describe the proper use of checked exceptions.

With all of this in mind, I believe it is better to require developers to "throws OurCompanysException" (as a checked exception) from methods where the design denotes validation takes place within the method, and only those methods or their clients, and enforced by the compiler.

I think the cost would be low, the interface more expressive, and the approach more flexible for where the clients handle planned exceptions differently to unplanned exceptions (for example, do not handle them but rather pass on up to the infrastructure/container).

Timothy


i need to loop in text like html source and ind spcfiy tet in it


This may be a repeat, but the thread has gotten long enough that it's difficult to read all the opinions.

Using exceptions properly is hard, just like designing good software is hard. The mistake you (Bruce) make is in thinking that using unchecked exceptions makes it easer to write good software. It really just changes the mistake lazy/hurried/forgetful developers will make from swallowing exceptions and continuing to missing exceptions and exiting/terminating. I don't think your choice will make "most" software better, just different. Either way you'll have to learn how to use exceptions properly and mistakes will be made.

I find the compiler's insistance that I deal with an exception helpful. Empty catch blocks stand as a reminder to others that something is being ignored. With unchecked exceptions that both are lost. No thanks.

Your insistence that because checked excecptions are an experiment that it somehow bolsters your argument is vacuous. Judge on the merits, not on novelty.

Lastly, I can't help but paraphrase Dennis Ritchie: "If you want Python or C#, you know where to get it."

Hans Ridder


May be I am missing something over here .
Assuming that an lowerlevel tiers throws an checked exception , say an SQLException the normal of handling it is catch this checked exception at next level and wrap it to something meaningful exception so that the upperlevel api understands this and acts accordingly.
Doing it this way will reduce the dependancy between tiers i.e. the top level tier need not worry the exceptions thrown by the lowest level tiers .
However in the ExceptionAdapter we are catching the exceptions which are not being documented by the methods
this is not very desirable from an end user's perspective who is using my code ..
VJai


Well, we should keep that checked exception but really need the option of treating it as a warning rather than error thus get it out of our way when not needed.

The real problem is the intrinsic difficulties in writing solid code and then misuse of tools by programmers. Majority of programmers, if not all of them, are mortals to various degrees, and they often worked under tight if not unrealistic schedule to write workable or barely workable code. If we want to write some code that works “just this circumstance we need”, we can write beautiful, uncluttered code that speak the logic clearly. But if we really need to "Write Solid Code", we will find the programming much less of fun. Yes, with all the grudge details. We have to be really paranoid and compulsory error-checker and handle every error with today’s ubiquitous usage of database and network. Needless to say, good error handling all the time is very hard. Then adding demand of performance, our programmers’ pain reached to another level.

Exception specification is something I personally felt sorely missing in C++ after coming back from Java. For example, I was especially unhappy with STL from major vendors. There's absolutely no exception specification to aid programmer. If exceptions were not caught at a point close enough, they were mostly useless. To enforce adequate exception specification and handling by our programmers, one way is checked exception and another is discipline we long know cannot be relied on. Like any other error checking, checked exception spoiled the fun for programming. But it does aid people to write more solid code. I could have agreed you if you are advocating that “check exception” should be treated as warnings rather than a compiling error. Wrapping everything into Runtime exception is a way to get the compiler out of our way but is also a step backward.

Boiled to bottom, Java is not a great language for expression or RAD and it's always very demanding to write solid code. Developers need to choose their tools and use them wisely. Good professional programmers will do better with more choices and casual programmers really need to choose a language best suit their needs (for example, a lot of financial analysts are happier with VB variants like Excel VBA rather than Java).

Without big vendor endorsements and zillion of dollars poured in, Java might never have reach the prominence of today thus get so many unsuspecting developers trapped. After all, it's just another programming language w/ a few improvements over C/C++ to make it easier to program and reuse code. Under different circumstance, Java may be a lousy choice. For example, languages like Python are really beautiful, easy to learn, expressive, and powerful without getting in way in teaching or testing or trying out ideas. And it doesn’t need checked exception (Yes, but instead as many grudging testing as possible with these dynamic languages if we need them to work “under all circumstances”!)

Luke


Good discussion, as I recently worked on a project where I was perplexed and amazed to see that they converted Java checked exceptions to unchecked exceptions. My initial thought was ridiculous, they are throwing away one of the main benefits of Java.

I talked to the "architect" about this and his reasoning was basically that checked exceptions are great if people know what they are doing, but they had run into some problems with how programmers coded (swallowing probably, I forget exactly what their issue was), so their solution was to make this major architectural design change, or decree, that all exceptions were unchecked.

So it seems in this example, here is something provided by Java to make your code more robust, and it is thrown away because people don't know how to use it.
My feeling is quite a bit of thought went into the design of Java, I'd be really suprised if this was thrown into Java when Gosling was on vacation. (Nice idea though).

From reading the comments above, I see mention of Meyer's "design by contract" and the idea of making the programmer think about how the exception should be handled. Further, I am in agreement with Brian Goetz (his article on DeveloperWorks pointed me to this discussion) in that checked exceptions are self documenting. (I do wonder whether folks who throw unchecked exceptions will really bother to document them as he suggests.)

Further I agree that exceptions are a difficult concept, however so is OOP in general (inheritance, interfaces, etc), and it is not implemented well, but that doesn't mean we should all switch to perl.

Brian's article:
http://www-106.ibm.com/developerworks/java/library/j-jtp05254.html

Mike O'Keefe
kupci2@yahoo.com


Addendum: I am by no means picking on C/perl/.. what have you, the right tool for the project.

Also, just to give you the sort of context for the project, in addition to the 'no checked exceptions' edict, we also were told:

-don't document the code because we're in a rush and it takes too long. I recall the frustration of a programmer trying to improve the performance of the system later upon looking at a bunch of classes with nary a single comment. Unbelievable.

-don't waste your time with JavaDoc. Now I'm someone who has a link to the JDK Javadoc in my browser, I use it all the time. Why not the same for custom code? No, we were told that we can just use WSAD's (Eclipse) refactor tools, i.e. shift+mouse click to select the interface, our use the outline view, etc, etc.

-no uml, rup, we're a XP shop. UML is only useful for postmortem. Nice, I'll mention that to Jacobson, Rumbaugh and Booch at the next OOPSLA, see what their take is. Besides, XP was sort of an excuse for no design, I'd say our process was more like 'wing it'.

-no design, customers decided screen design, etc.

-Unit tests are only to build the code, once the code is built, we throw it away, i.e. not maintained for bug fixes, new versions.

-Somehow we managed because we got other things right (use of patterns, great open source tools (Jakarta Struts, Tiles, etc) excellent programmers, great Ant build script, great support from IBM

So anyway, 'unchecked exceptions' somehow made sense for that project.


As a very early Java developer, I had written a lot of java code with exceptions BEFORE exceptions were checked. Getting that code to compile after they added checked exceptions was very hard, and I hated checked exceptions.

For a year or two after that I continued to hate checked exceptions.

Then I realized that the way to handle them is to address them by either catching (and not ignoring) the exception, OR, declaring your method as throwing the very exception you're not willing to catch. A lot of the time I declare MY method as throwing the exception, which means I don't have to deal with it right there, but does mean that I cannot ignore the fact that there is a good chance it will be thrown and somebody ELSE must deal with it.

There are times when an interface does not throw an exception that a particular implementation might like to throw. That is an annoying problem.

Jonathan Payne
jpayne@gmail.com


This is a nice discussion, though a little long to read it all. I have some comments:

1. When was this article written? I don't see any dates. I will presume that it predates 1.4's chained exceptions.

2. I have some qualms with the actual implementation of

ExceptionAdapter
. For example, why keep a copy of the stack trace when
originalException
maintains it for you.

3. You might want to take a look at the source for

java.lang.reflect.InvocationTargetException
. This is how Sun (or at least someone at Sun) thought it was best to wrap exceptions. You could even copy the code, change the name, and change the parent from
Exception
to
RuntimeException
. (As of 1.4 it was retrofitted to use chained exceptions, so look at 1.3.x if that's what you want.)

5. The problem with checked exceptions is that they are just as hard to design as the rest of a project's API. If a method needs to throw an exception and the design didn't so designate, then changing the design for this is just as hard as if it were a change to the method's argument list. The thing is that architects put more effort into the argument lists than into the throws clauses. (Or so it seems to me.)

6. I agree that "bubbling up" isn't taught well. It's often not used well, either. For example, when I should write

public void foo() throws exA, exB, exC, exD
, I am tempted to be lazy and just write
public void foo() throws Exception
, which is no good.

5. People have listed examples of exceptions that are used badly in Sun's API, such as

Thread.sleep()
and
Integer.parseInt()
. The one that has bothered me lately is
javax.swing.text.MaskFormatter
. Let me quote myself from page 723 of 'Java Swing, 2nd ed.':

"The

mask
property described earlier is key to
MaskFormatter
. It can be set in the constructor or through the
setMask()
method, both of which are declared to throw a
ParseException
if the mask in invalid. This is an annoyance because the only way to make an invalid mask is to escape a literal (or to put a single
'
at the end), and even then no exception actually gets thrown (at least not in Version 1.4.1)."

So to use one of these things, the compiler forces you to write a try/catch clause even though an inspection of

MaskFormatter
's source code shows it can never be called. I can see how this could happen. It made sense to the API architect that a mask could be invalid but the implementor coded in such a way that the exception never needs to be thrown. But still, I find such situations vexing, and they seem to come up all too frequently.


Arg, my comment is virtually unreadable because I expected <code> to inline code text instead of putting it on a new line with space above and below.

Sorry about that. If I'm able, I'll attempt to repost.


This is a nice discussion, though a little long to read it all. I have some comments:

1. When was this article written? I don't see any dates. I will presume that it predates 1.4's chained exceptions.

2. I have some qualms with the actual implementation of ExceptionAdapter. For example, why keep a copy of the stack trace when 'originalException' maintains it for you.

3. You might want to take a look at the source for java.lang.reflect.InvocationTargetException. This is how Sun (or at least someone at Sun) thought it was best to wrap exceptions. You could even copy the code, change the name, and change the parent from Exception to RuntimeException. (As of 1.4 it was retrofitted to use chained exceptions, so look at 1.3.x if that's what you want.)

5. The problem with checked exceptions is that they are just as hard to design as the rest of a project's API. If a method needs to throw an exception and the design didn't so designate, then changing the design for this is just as hard as if it were a change to the method's argument list. The thing is that architects put more effort into the argument lists than into the throws clauses. (Or so it seems to me.)

6. I agree that "bubbling up" isn't taught well. It's often not used well, either. For example, when I should write 'public void foo() throws exA, exB, exC, exD', I am tempted to be lazy and just write 'public void foo() throws Exception', which is no good.

5. People have listed examples of exceptions that are used badly in Sun's API, such as Thread.sleep() and Integer.parseInt(). The one that has bothered me lately is javax.swing.text.MaskFormatter. Let me quote myself from page 723 of 'Java Swing, 2nd ed.':

"The 'mask' property described earlier is key to MaskFormatter. It can be set in the constructor or through the setMask() method, both of which are declared to throw a ParseException if the mask in invalid. This is an annoyance because the only way to make an invalid mask is to escape a literal (or to put a single ' at the end), and even then no exception actually gets thrown (at least not in Version 1.4.1)."

So to use one of these things, the compiler forces you to write a try/catch clause even though an inspection of MaskFormatter's source code shows it can never be called. I can see how this could happen. It made sense to the API architect that a mask could be invalid but the implementor coded in such a way that the exception never needs to be thrown. But still, I find such situations vexing, and they seem to come up all too frequently.


One area where checked exceptions drive me nuts is
during stream closing. It seems to take WAAAY too
many lines of code to make sure a stream is closed
properly.


void foo() {

    InputStream in = null;
    OutputStream out = null;

    try {
        in = new FileInputStream("foo.txt");
        out = new FileOutputStream("foo2.txt");

        // do some stuff with in/out

    } catch (IOException e) {
        println("something bad happened");
    } finally {
        if (in != null) {
            try {
                in.close();
            } catch IOException(e) {
                println("whooops!");
            }
        }
        if (out != null) {
            try {
                out.close();
            } catch (IOException e) {
                println("whooops 2!");
            }
        }
    }
}


Very interesting discussion. It has contributed to making me think more about Exceptions.

I am left with a couple of thoughts. First, there was a comment made about the nature of "errors". I find this very accurate. We must understand what the end user expectation of software is. I would argue that most end users are not very tolerant of problems that cause the system to terminate in some unknown unacknowledged manner. In addition, such problems lead to increased costs for many software producers in support calls etc.

What I am wondering is the following. The Exception debate so far has focused on checked vs. unchecked "Exceptions". Of the many troublesome aspects of unchecked "Exceptions" is their ability to bring a system to a very abrubt termination. In this sense unchecked "Exceptions" are no different than an error. Which is my thought.

The java hierachy includes two types under the common Throwable, both "Error" and "Exception". Error types are not required to be handled and are known to result in most cases with an abrubt termination of the application. They are true "error" situations. However, unhandled unchecked exceptions seem to produce similar situations in many cases.

What is important to realize I think is that since both "checked" and "unchecked" Exceptions are both subtypes of Exception, they should be handled in some manner by nature of the concept of "exception being non fatal gracefully if nothing else", while error being fatal.

The hard part with unchecked exceptions is identifying what ones are possibly thrown. This leads to the documentation. Unchecked exceptions could be required to be declared in the thows clause as well as checked exceptions. Perhaps the compiler could enforce this aspect to enforce the documentation but not require them to be "caught".

This may ease the burden of identyfing and dealing with unchecked exceptions so that they don't wind up as "Errors" which most do today.

I can see both sides to this discussion and thank everyone for forcing me to see this idea in a better light.

Scott
saroehr@hotmail.com


I must object strongly. Checked exceptions are good as they contribute to handling errors cleanly. If you don't like them, wrap them in RuntimeException(Throwable t), but bear the consequences. However, I personally prefer to wrap them in custom checked exceptions. JDK 1.4 supports both types of wrapping (printStackTrace() contains the original exception and getCause() method retrieves it).

Dusan Chromy
Information Specialist
EDS


I think the current checked exceptions that are in the JDK should have all been RuntimeExceptions and we wouldn't be having these discussions. People who really wanted to throw, declare, and catch checked exception would be entitled to do so and those who didn't wouldn't have to.


I forgot include my name/email in the above post.

Ian deSouza
ian.a.desouza@gmail.com

By the way, what I've done to get around the annoyance of Java checked exceptions is to write wrapper actors around the method calls that throw exceptions and then wrap them in RuntimeException and rethrow. I therefore don't swallow the exception and don't have to declare the litany of exceptions that something like the reflection packages makes us do (as well as all the clients all the way up the stack trace).


Here's a little proposal that offers some help in this area:
http://yost.com/computers/java/finally-throwable.html

Dave Yost


If checked exceptions are a real must and they wanted you to do something to catch the exception why do they let you specify empty code blocks for the caught exception ???

C# is every bit as good as java if not better, and I think that checked exceptions are a waste of time as normal exceptions bubble up.

Imageine calling 12 function, each function throw's 2 exceptions (every exception is unique), you have to catch 24 exceptions !!! That would look like a nice bit of code.

Adrian Bezzina
AdrianRBezzina@hotmail.com


fuck you then askholes!!!!!!!! try to fuck some dogs it may fit your never ending taste of the fucking sex hormone thing.


You can also soften checked exceptions with use of AspectJ.


While checked exception might look like compile time type checking, there is one thing very different. Type checking are typically quite accurate: if you are writing a routine to find the sine of some (real) value you always get a double. At times you might be able to trim down the possibilities a little bit because you know a bit better than the compiler (e.g., you know that you always pass it an integral multiple of PI/2), but most of the time you'd ignore the narrowing of domains. If your function is written specifically expecting doubles as input, getting a String into it really would not end up very well most of the time. So (nearly) everytime you use compile time type checking, you win a little bit, e.g., by knowing that you are not assigning a double value into a char.

Exceptions are opposite. They don't (usually) happen. So unlikely, indeed, that compile-time information is very inaccurate. Say you are opening a file, read two lines from it, turn both lines into a number, and close the file. Naturally, compile-time information must say that you might have the file non-exist, file permission doesn't allow your access, the file doesn't have 2 lines so you get premature EOF, the line isn't numeric so you get a conversion error, and some more (less common) causes for failure. But if that file is one that you handed from another program or even function you write, and that program simply write two numbers into the file and exit, none of the "exceptional condition" would make any sense to you. You'd like to get away with writing any code to deal with the exception, but then, you must, because somehow the language designers forced you into that. That's not hypothetical. There are many times that I have similar experiences to a few days ago when I must deal with "InterruptedException" in a call to wait(), even though my whole program contains no call to interrupt().

Because compile time information is so inaccurate, every time you work with checked exception you lose a bit, instead of win a bit as in the case of static type checking. Exceptions are inheritly a run-time entity. There are too many circumstances that there is simply no perceivable reason why a "possible" (from the eye of the compiler) exception could come out, that the (really) best solution is simply to let it terminate the program completely with a stack trace so that you can analyze it and fix the real cause of the problem rather than the symptoms of getting an exception.


Interesting discussion - I've actually read most of it; of cource with a few exceptions :-)

I've been working alot with software design, security and error handling (which actually often weaves into security because causing errors often compromizes security)...

A very bad way to handle any form of exception is to just discard them when they occur. Propper error handling involves throwing exceptions further on. To get useful error messages for developers and at the same time understandable messages to end-users, you should add your own code to exceptions before throwing it further.

Proper error handling will greatly reduce runtime bugfix.

-- SteinBjarne@hotmail.com


Phew! This discussion will never end, will it.
And we'll perhaps never get anywhere near a conclusion.

I think checked exceptions cannot be done away with in Java.
Sense or not, it will sure lead to protests if Sun tries to
dilute compiler support for checked exceptions.

But I have been toying with this idea below, not sure someone
already expressed exactly this in the list:

Checked exceptions may always be indicated and respected in
java code. But let there be a syntactic way of propagating one
or more checked exceptions without the nasty try-catch-rethrow
code being necessary.

How about this:

1. Consider three methods a(), b(), c() which call three different
checked exceptions (say, IOException, SQLException and something
else.

2. Consider code that needs to use them.



public class Employee
{
  public Dossier fetchDossier()
    rethrows DossierException
  {
    ... 
    a();
    ...
    b();
    ...
    c();
  }
}

On finding a checked exception with the _rethrows_ clause, Java will
automatically wrap (1.4-style) a checked exception thrown, into this
rethrowable type and throw that exception further on.

This will achieve the possible benefits:

a. Eliminate the clutter of exception rethrow code.
b. Ensure that the original exception is not lost, since
the compiler now takes charge of the rethrow.
c. Decrease the chances of the programmer writing empty catch blocks.
d. Encourage designers to work on context-specific exceptions
and dissuade them from rethrowing the same exceptions out-of-context.

I would love to hear from Bruce and others on what they think of this.

Ashwin Stuart
equinus100-at-hotmail-dot-com


(1) ...an untried experiment

The same can be said for brakes on early automobiles. The observation is neutral with respect to the beneficial or detrimental effects of checked exceptions. I don't think Bruce was implying this is necessarily negative but some might interpret it that way.

(2) ...a failure because so many people end up swallowing the exceptions in their code.

That so many people end up writing procedural code in C++ and Java means object-oriented languages are a failure. I think this is a case of pencilitus: it hurts when I stick this pencil in my eye.

Most people can't seem to grasp the distinction between user input errors, exceptions in the natural environment and hard programming errors, let alone how to handle each. That helps keep knowledgable folks like myself at the top of the resume stack so I'm not complaining.

(2) a failure because so many people end up swallowing the exceptions in their code.


Checked exceptions are sometimes useful but sometimes they are getting in the way. I add

throws
if they shouldn't be handled in the context I'm working on. However, sometimes the list of exceptions in the
throws
clause gets too long, and the code becomes difficult to read.

As a programmer, I want to be able to express explicitly that "exceptions are NOT handled here" without having to enumerate *all* of them. I want the compiler to move all the checked exceptions one level up, without swallowing them and without loosing information. I would want to code something like:


public class EmployeeReader  {

    public Employee readEmployee() throws {
        // ... 
        // some useful code
        // ... 
    }
}

The semantics of the above "unspecific

throws
" is that any checked exception is automatically escalated to the caller. This is different from:
    public Employee readEmployee() throws Exception {...} 

where information is lost – it is impossible for the caller to know which *specific* exceptions might be thrown.

Now, when I come to catch exceptions, I want to handle them *specifically* (as opposed to

catch (Exception e)
), but without duplication. I would want to code something like:

     try {
         // do something
     }
     catch (RecordStoreException e1, IOException e2) {  // possibly a longer list 
         // a common handler 
     }

The above suggestions can help make the code shorter, more readable, and easier to write. They maintain the advantage that checked exceptions have, namely, that there are no “surprise exceptions” – the programmers always know which exceptions a method might throw. They can make minded dedications whether to catch or escalate them. When catching, the programmers can write handlers that catch multiple *specific* exceptions and handle them together. All those benefits are achieved while still remaining fully backward compatible.

Barak Naveh


I quite disagree with Bruce's attitude about Java exceptions.
First, there are 3 things of throwable stuff in Java:
- Checked exceptions (derived from Exception but not from RuntimeException) - stuff that can occur, and is more or less recoverable, like not finding a file, like a socket error
- Runtime exceptions (derived from RuntimeException), stuff that can occur, can be recoverable or represents a bug, but can occur that often that you don't want to fill your code with things like:
public void method() throws NullPointerException, ClassCastException, NumberFormatException, ArithmeticException
- Errors: usually unrecoverable things, like: out of memory, messed up JVM, big big bugs (assertion errors), etc

The rule of thumb: describe what you cannot process in your method through the throws clause, so that others know what to expect. If you don't want to process, let it pass through your method using the throws clause, but let the programmer that uses your method to know that you didn't handle the problem!
Thus, letting everything to be runtime exception would create a huge mess - nobody will know that would really happen badly in the code.

My way of handling things I don't handle (like cases that *I know* that they shouldn't appear, i.e. reading a file that you just wrote 100 milliseconds before): embed them in errors. Also, the same treatment I use for cases in which my code detects a bug, like after a switch statement, the default choice should NEVER be followed). Why Error and not RuntimeException? To avoid the case when a wise guy does a catch(Exception e){} and the problem in my code remains undetected. Why my model works? Because I don't usually write servers, and when I do, I still want them to run reliably: if I really have a bug, I preffer them to crash and I get informed and I fix the bug rather than outputing nonsense.
Another thing: if I don't want to be very concerned with exceptions, I always declare the main method as:
public void main(String[] args) throws Exception.

My idea is that if you (the programmer) don't know how to handle Exception-based programming, don't take the job.

Marian Olteanu (gmail account: marian.olteanu)


On the Java side, this is my (simple) exception handling policy (and I believe only simple coding policies are actually followed):

1. If you don’t want to or can’t handle it in the method, throw it upwards (throws); before you do that, you may want to print out some context info anyway to aid understanding the problem after the fact.
2. Always catch Exception at the module boundary so that it doesn’t crash something or lose error info.
3. When exception occurs, don’t be afraid to print as much relevant info as possible – it’s not working out anyway, don’t worry about penalty of a fraction of a second.

On the C# side, instead of arguing how bad checked exceptions are or whether Java’s was a bad experiment, at least GIVE ME THE OPTION to turn on warnings of potential unhandled exceptions. The compiler even prints warnings on unused members. Exceptions seem to be a bit more important than that!

Bill Shen
byshen@hotmail.com


If you are intrested in state of the art exception handling, take look at conditions in Common Lisp. Exellent short paper of the subject is http://www.nhplace.com/kent/Papers/Condition-Handling-2001.html

Search     Home     WebLog     Consulting     Seminars     Calendar     Books     CD-ROMS     Newsletter     About     Contact     Site Design     Server Maintenance     Powered by Zope
©2007 MindView, Inc.