Did you know? DZone has great portals for Python, Cloud, NoSQL, and HTML5!

As an Agile Coach, Miško is responsible for teaching his co-workers to maintain the highest level of automated testing culture, allowing frequent releases of applications with high quality. He is very involved in Open Source community and an author of several open source projects. Recently his interest in Test Driven Developement turned into http://TestabilityExplorer.org with which he hopes will change the testing culture of the open source community. Misko is a DZone MVB and is not an employee of DZone and has posted 38 posts at DZone. You can read more from them at their website. View Full User Profile

Checked Exceptions I Love You, But You Have to Go

09.17.2009
Email
Views: 11245
  • submit to reddit

Once upon a time Java created an experiment called checked-exceptions, you know you have to declare exceptions or catch them. Since that time no other language (I know of) has decided to copy this idea, but somehow the Java developers are in love with checked exceptions. Here, I am going to “try” to convince you that checked-exceptions, even thought look like a good idea at first glance, are actually not a good idea at all:

Empirical Evidence

Let’s start with an observation of your code base. Look through your code and tell me what percentage of catch blocks do rethrow or print error? My guess is that it is in high 90s. I would go as far as 98% of catch blocks are meaningless, since they just print an error or rethrow the exception which will later be printed as an error. The reason for this is very simple. Most exceptions such as FileNotFoundException, IOException, and so on are sign that we as developers have missed a corner case. The exceptions are used as away of informing us that we, as developers, have messed up. So if we did not have checked exceptions, the exception would be throw and the main method would print it and we would be done with it (optionally we would catch in main all exceptions and log them if we are a server).

Checked exceptions force me to write catch blocks which are meaningless: more code, harder to read, and higher chance that I will mess up the rethrow logic and eat the exception.

Lost in Noise

Now lets look at the 2-5% of the catch blocks which are not rethrow and real interesting logic happens there. Those interesting bits of useful and important information is lost in the noise, since my eye has been trained to skim over the catch blocks. I would much rather have code where a catch would indicate, pay, attention here something interesting happens here, rather than, it is just a rethrow. Now, if we did not have checked exceptions, you would write your code without catch, test your code (you do test right?) and realize that under these circumstances an exception is throw and deal with it. In such a case forgetting to write a catch block is no different than forgetting to write an else block of the if statement. We don’t have checked ifs and yet no one misses them, so why do we need to tell developers that FileNotFound can happen. What if the developer knows for a fact that it can not happen since he has just placed the file there, and so such an exception would mean that your filesystem has just disappeared and your application is not place to handle that.

Checked exception make me skim the catch as most are just rethrows, making it likely that I will miss something important.

Unreachable Code

I love to write tests first and implement as a consequence of tests. In such a situation you should always have 100% coverage since you are only writing what the tests are asking for. But you don’t! It is less than 100% because checked exceptions force you to write catch blocks which are impossible to execute. Check this code out:

bytesToString(byte[] bytes) {
  ByteArrayOutputStream out = new ByteArrayOutputStream();
  try {
    out.write(bytes);
    out.close()
    return out.toSring();
  } catch (IOException e) {
    // This can never happen!
    // Should I rethrow? Eat it? Print Error?
  }
}

ByteArrayOutputStream will never throw IOException! You can look through its implementation and see that it is true! So why are you making me catch a phantom exception which can never happen and which I can not write a test for? As a result I cannot claim 100% coverage because of things outside my control.

Checked exceptions create dead code which will never  execute.

Closures Don’t Like You

Java does not have closures but it has visitor pattern. Let me explain with concrete example. I was creating a custom class loader and need to override load() method on MyClassLoader which throws ClassNotFoundException under some circumstances. I use ASM library which allows me to inspect Java bytecodes. The way ASM works is that it is a visitor pattern, I write visitors and as ASM parses the bytecodes it calls specific methods on my visitor implementation. One of my visitors as it is examining bytcodes decides that things are not right and needs to throw a ClassNotFondException which the class loader contract says it should throw. But now we have a problem. What we have on a stack is MyClassLoader -> ASMLibrary -> MyVisitor. MyVisitor wants to throw an exception which MyClassLoader expects but it can not since ClassNotFoundException is checked and ASMLibrary does not declare it (nor should it). So I have to throw RuntimeClassNotFoundException from MyVisitor which can pass through ASMLibrary which MyClassLoader can catch and rethrow as ClassNotFoundException.

Checked exception get in the way of functional programing.

Lost Fidelity

Suppose java.sql package would be implemented with useful exception such as SqlDuplicateKeyExceptions and SqlForeignKeyViolationException and so on (we can wish) and suppose these exceptions are checked (which they are). We say that the SQL package has high fidelity of exception since each exception is to a very specific problem. Now lets say we have the same set up as before where there is some other layer between us and the SQL package, that layer can either redeclare all of the exceptions, or more likely throw its own. Let’s look at an example, Hibernate is object-relational-database-mapper, which means it converts your SQL rows into java objects. So on the stack you have MyApplication -> Hibernate -> SQL. Here Hibernate is trying hard to hide the fact that you are talking to SQL so it throws HibernateExceptions instead of SQLExceptions. And here lies the problem. Your code knows that there is SQL under Hibernate and so it could have handled SqlDuplicateException in some useful way, such as showing an error to the user, but Hibernate was forced to catch the exception and rethrow it as generic HibernateException. We have gone from high fidelity SqlException to low fidelity HibernateException. An so MyApplication can not do anything. Now Hibernate could have throw HibernateDuplicateKeyException but that means that Hibernate now has the same exception hierarchy as SQL and we are duplicating effort and repeating ourselves.

Rethrowing checked exceptions causes you to lose fidelity and hence makes it less likely that you could do something useful with the exception later on.

You can’t do Anything Anyway

In most cases when exception is throw there is no recovery. We show a generic error to the user and log an exception so that we con file a bug and make sure that that exception will not happen again. Since 90+% of the exception are bugs in our code and all we do is log, why are we forced to rethrow it over and over again.

It is rare that anything useful can be done when checked exception happens, in most case we die with error, so make that the default behavior of my code with no additional typing.

How I deal with the code

Here is my strategy to deal with java:

  • Always catch all checked exceptions at source and rethrow them as LogRuntimeException.
    • My runtime un-checked exception which says I don’t care just log it.
    • Here I have lost Exception fidelity.
  • All of my methods do not declare any exceptions
  • As I discover that I need to deal with a specific exception I go back to the source where LogRuntimeException was thrown and I change it to <Specific>RuntimeException (This is rarer than you think)
    • I am restoring the exception fidelity only where needed.
  • Net effect is that when you come across a try-catch clause you better pay attention as interesting things are happening there.
    • Very few try-catch calluses, code is much easier to read.th
    • Very close to 100% test coverage as there is no dead code in my catch blocks.

 

From http://misko.hevery.com

Tags:
Published at DZone with permission of Misko Hevery, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Simon Martinelli replied on Thu, 2009/09/17 - 2:11am

The problem of checked exception is that they are missunderstood! For example: It doesn't make sense that the java.io package throws IOExceptions that are checked.

BUT! In business code I like them because they are part of the interface and they say: Hey there went something (business relevant) wrong!

Business exceptions are the only reason for use checked exceptions.

Casper Bang replied on Thu, 2009/09/17 - 2:21am

I totally agree, which is why I've tewaked my own version of javac to give me a little more legroom:

http://coffeecokeandcode.blogspot.com/2009/08/tweaking-javac-leniency.html

Tony Siciliano replied on Thu, 2009/09/17 - 7:15am

Checked exceptions are an essential part of a method's contract, specially when the method being called depends on the availability of an external system, such as a database, file system, network, etc.

Writing "meaningless catch blocks" is evading responsabilties of programing by the method´s contract, and complaining that it hinders personal convenience. This is also probably why checked exceptions are one of the most misused features of Java.

SQLException, IOException are both accurately defined as checked exceptions. You're the one responsible for handling those and other failures gracefully. If there are cases where you can't do much, there are many others where it is of prime importance that you do something other than just printing the exceptions, logging them, or rethrowing them where they should'nt be handled.

Yes, checked exceptions have been a failed experiment, less because of the Java exception model itself , more because most Java programers have failed to acknowledge the two basic causes of method failure.

Ricky Clarkson replied on Thu, 2009/09/17 - 4:29am

Exceptions are conceptually just another form of return value.  A method that returns a String or throws a Failure can be easily altered so that it returns Either<String, Failure>.  And that'll work better with Misko's functional code.

Mario Fusco replied on Thu, 2009/09/17 - 5:47am

I totally agree and I argumented exactly the same here (together with other things I don't like of Java).

Anyway if you read the comments to my article you will discover that lots of people actually love checked exception even if I am still wondering why.

Gerd Ziegler replied on Thu, 2009/09/17 - 7:37am

I found it useful to just throw declared Exception when I want to tell the caller that there may be some exceptions  he has to be aware of, but I always use the same type, plain Exception. So if someone doesnt care he just declares throws Exception. It's some kind of middle way between always using RuntimeExceptions and always declaring every possible exception type/rethrowing.

Steven Baker replied on Thu, 2009/09/17 - 8:13am

totally agree with Tony S.

not handling exceptions properly is just plain undisiplined coding

Mladen Girazovski replied on Thu, 2009/09/17 - 8:57am

The argument checked vs. unchecked exceptions has been fought long ago, what puzzles me is that some people still think that checked Exceptions are a good thing...

Forcing a client to handle an Exception even if there is no way to handle it produces these empty catch blocks, it can also break encapsulation, if i'm forced to delegate a low level Exception to a higher layer.

Rigel Kentaurus replied on Thu, 2009/09/17 - 9:16am

Remember C++? We could throw not an Exception object, but actually any kind of object. There were no restrictions. Going back to my code I even used to throw integers (that were my error codes). I wouldn't do that today, but it was a nice example of what "throws" meant before we got the concept of an exception.

The only positive point that I have found with exceptions is that it helps novice developers. Sometimes human nature converges with the "less possible effort" paradigm, meaning that if I don't have to write a catch block for that, i won't. And soon enough that RecordExistsException or SqlDuplicateKeyException are thrown all the way to the VM level. And in a web application that is really bad, as you can spend hours debugging if it was the view, the controller, the method, the DAO call, an inner class to JSF .... an scenario where an expert would spot the exception right on and say "it's this method because of this", a new developer would be lost in all the layers of a simple application.

With checked exceptions they have no other option than to catch them, so the code will compile. Granted most of them would do silly things like eating them and not doing anything useful (thus leaving an UI unsynchronized, the impression of an operation completed that was not because it really threw an exception)... so one would wonder if it was really an advantage. On one side, you make the developer really aware that there are some errors that they must deal with. In the other way you are just hiding important logic.

Greg Roodt replied on Thu, 2009/09/17 - 9:36am

I agree with the article, checked Exceptions should be avoided. Working with checked exceptions correctly, like working with concurrency is hard. With good developers and discipline, it is possible that checked Exceptions could be used successfully. But is all this extra effort worth it? Its easier to get it wrong than it is to get right, and it does often leave dead blocks of untestable code.

 I like the strategy introduced at the end of the article and Im interested in applying it to the next project I work on.

Jeff Knecht replied on Thu, 2009/09/17 - 9:47am in response to: gerdziegler

@Gerd: I hope I never have to use one of your API's.  You've taken a bad situation and made it worse: not only do I have to surround my calls to your API with a try/catch block, but I cannot even be sure which exceptions I might actually have to handle.

Magnus Smith replied on Thu, 2009/09/17 - 10:14am

 

Hey, imho checked exceptions are just great.

Its just that sometimes people write the code without thinking things through.  The real thing that a developer needs to be clear about exactly what they are trying to achieve by choosing a checked exception over an unchecked one.  Once they are clear with that then they need to apply it in a consistent manner. 

Checked exceptions signal to the client that something has happened and they need to do something about it.

If you are just swallowing the checked exception then in most cases either you are ignoring something important that you should really deal with or the person who wrote the code that you are calling should not have used an checked exception as there was no reasonable action for you to take.

When people use checked exceptions where unchecked exceptions should be used then developers writing the client code get irritated or confused because they have to write do-nothing code to handle it.   This can be really annoying as you are often cleaning up other peoples mess.

 

I found this Barry Ruzek article Effective Java Exceptions

to be really very good.  

 He suggests the following mapping of how to choose a checked or unchecked exception.

Condition
Contingency Fault
Is considered to be A part of the design A nasty surprise
Is expected to happen Regularly but rarely Never
Who cares about it The upstream code that invokes the method The people who need to fix the problem
Examples Alternative return modes Programming bugs, hardware malfunctions, configuration mistakes, missing files, unavailable servers
Best Mapping A checked exception An unchecked exception

 The article also gives good advice about using a fault barrier to avoid endless catch-and-rethrow scenario.

 

Fabrizio Giudici replied on Thu, 2009/09/17 - 10:27am

I totally disagree. Frankly, I find the "must catch - rethrow", being repeated for years, argument totally invalid.

First, because checked exceptions are a tool, and you decide when to use a checked or an unchecked exception. If there's a misuse of checked exceptions in the Java runtime, it's a problem of the runtime, not of the language feature.

Second, often the catch-rethrow MUST BE DONE because an exception changes meaning. What I'm catching as an IOException at a certain level usually means another type of failure at the business level. So, catch-rethrow in this case is a feature that a good design should consider, not a thing that I'm compelled to do because of the language.

One of the most common things that I'm seeing in customer's code is something like: Applet - calls via SpringRemoting a - Remote Service - that calls Hibernate. Of course, there's no Hibernate.jar in the Applet, as it shouldn't be there. Now, it happens that an operation on the database fails, throw a HibernateException subclass (which is a RuntimeException, so nobody caught is), gets serialized to the Applet and - ta-dah - you get a wonderful ClassNotFoundError - and the customer can't understand what's happening. Letting exceptions filter to the upper level without any check is mostly an error, especially in multi-tier applications.

Third. You're all thinking of good applications with a good test coverage, where all my cases for checked exceptions could be replaced by a very good test coverage. Now, please do a reality check. We are in the minority that write good coverages, that is a minority of people writing decent tests. That's bad, but that's life. This is not going to change in any way, neither in the short, nor in the medium period (I don't do long period forecasts by principle). In this world, having the compiler to provide some more checks with static means is a very good thing.

 

Gilberto Olimpio replied on Thu, 2009/09/17 - 10:31am

I agree with Simon about the "business exceptions".
It's common to see developers that don't care about the unchecked exceptions and we have to heard from the user that a "strange message" (a.k.a. stack trace) appears on his browser/screen...and that's a shame, exceptions should never appears on the user's screen.
I know...this kind of issue can be avoided by writing more efficient tests and hiring good developers, but good/efficient tests are not so easy to develop and even good developers are tempted to ignore unchecked exceptions when they are under pressure.

Alex(JAlexoid) ... replied on Thu, 2009/09/17 - 11:17am in response to: jknecht

@Gerd: I hope I never have to use one of your API's.  You've taken a bad situation and made it worse: not only do I have to surround my calls to your API with a try/catch block, but I cannot even be sure which exceptions I might actually have to handle.

  Then you probably have to stay away from Java, since, you know, NPE is always around the corner in most Java API. Most of them are not even delcared and/or hidden by delegation or abstraction.

Alex(JAlexoid) ... replied on Thu, 2009/09/17 - 11:31am in response to: fabriziogiudici

I agree partially. I believe that exceptions have to be checked and "transformed" only at logical boundaries, not technical ones. Logical being sending a fault message over the network, and technical is API call. Spring Remoting is the culprit in your case, because it implies that there is no transformation during calls. On those boundaries, you have to catch all, including all RuntimeExceptions and Errors.

 As a result of misuse of checked exceptions by core java API, we have some methods that have a dozen or so of declared exceptions in the trows clause. Or worse yet silent failure.

Yet, checked exceptions are very good in cases where the whole interface contract is about: If I fail some operation, you have to handle it correctly.

As a result of people wrapping some exceptions in several layers, I have seen stack traces with over 1000 elements. And at the end, there is a network connection timeout, witch is very understandable to most users or at least yields an understandable bug report and not something like: OperationCouldNotBeCompleted {...snip...} ... xx more elements in stack trace ....

Johannes Brodwall replied on Thu, 2009/09/17 - 11:39am

Checked exceptions is a totally failed experiment. @Fabrizio: Talk for yourself. My code have 80% coverage (total test suite run in < 10 seconds). Of the remaining 20% about 15% is checked exceptions. Why should your sloppy programming hurt my code coverage? @Magnus: Your argument sounds nice in theory, but can you come up with one example of an checked exception that would not be better as an unchecked exception and how you'd deal with it? It's about time we dropped this error generating, code rotting, disgusting feature that no other language than Java has ever had or missed!

Johannes Brodwall replied on Thu, 2009/09/17 - 11:41am

Oh, one more thing, for those who don't realize it: Removing complier checks for checked exceptions is a totally backwards compatible change. All existing source code would still compile if the language removed the concept of checked exception.

Jeff Knecht replied on Thu, 2009/09/17 - 12:11pm in response to: jalexoid

Then you probably have to stay away from Java, since, you know, NPE is always around the corner in most Java API. Most of them are not even delcared and/or hidden by delegation or abstraction.

 Indeed, all RuntimeExceptions are always around the corner.  In most cases, these are not declared to be thrown; so my client code can choose to either explicitly catch it, trap for it ahead of time, or let it bubble up to clients of my API. 

But declaring that a method 'throws Exception' eliminates that option for me.  If I want runtime exceptions to bubble up to a higher layer in the application, I have to handle the runtime exceptions myself.  If I want to handle a each type of checked exception individually, I am still forced to handle the top-level Exception, even though the code is unreachable.

Consider whether you really want your code to look like this:

try {
gerdsapi.processFile(myFile); // potentially throws IOException or DataFormatException
// but method is only declared to throw Exception
} catch (RuntimeException re) {
// I have to do this because Gerd refuses
// to declare the actual checked exceptions his
// API might throw.
throw re;
} catch (IOException ioe) {
throw new BusinessException("Error reading the file");
} catch (DataFormatException dfe) {
handleDataFormatProblems(myFile);
return false;
} catch (Exception e) {
// This block is unreachable. Thanks, Gerd!
}

 

 

Jilles van Gurp replied on Thu, 2009/09/17 - 12:27pm

I've been coming around slowly from the checked into unchecked camp. I'm not 100% there yet because I'm just seeing just too much crappy code where people do catch Exception (i.e. the parent class: evil) and end up catching NPEs, etc. as well without doing anything with it (like telling wtf is going on). The try .. catch is just done preemptively since there aren't any checked exceptions but you never know what this spring stuff might do and error pages are ugly. Not my code, but I did spend quite a bit of time play detective and hunting down a swallowed NPEs this way. Also, I wasted  two hours this week on a swallowed (by Spring) JDBC exception and rethrown, meaningless run-time exception that crucially did not inform me I was violating some constraint in my database that I could fix in 1 minute.

When Java starts to feel like a stupid scripting language where you just run your code in order to figure out if you actually did the right thing, something is wrong in my view. On the other hand, I appreciate not having to litter my code with useless catch blocks as well.

 

Trevor Williams replied on Thu, 2009/09/17 - 1:16pm

I have to take issue with your unreachable catch clause example.  Yes, in this specific case you have an unreachable catch, but it's not because of any inherent behaviour of checked exceptions.

When you override or implement a method declared in a parent class, you are free to include any subset of the parent declaration's exceptions, including none, in your throws clause.  If you declare a variable of the subtype, you need only deal with the specific exceptions that the subtype throws.  If your variable is declared as the parent type, you must be able to deal with any exceptions that any of its subclasses might throw, because you've explicitly stated that you do not know which subtype you are working with.

In fact, that's how ByteArrayOutputStream works, for the most part.  None of the write() methods throws IOException, and since your variable is a ByteArrayOutputStream instance, you don't have to catch them.  The reason that your example has an unreachable catch clause is that for reasons beyond my comprehension, close() throws IOException.  There's no reason for it to do that, but it does.  That is an implementation issue for that class, not a flaw of checked exceptions.

As far as the NPE argument goes, if you're getting NPEs, your code is failing to test for null.  Your fault.  Period. Same goes for ArrayIndexOutOfBounds and a bunch of other RuntimeExceptions that will never happen in well-formed code.  That's why they're unchecked, you shouldn't ever have to catch them.

Collin Fagan replied on Thu, 2009/09/17 - 1:38pm

I don't agree. Maybe you can get away with writing code that just randomly fails, but I can't. In my opinion runtime exceptions are evil. Programmers, like you, assume they know what constitutes an "unrecoverable condition" in my code. You don't, end of story. Not telling me how you will fail means I can't possibly plan ahead. I can't protect my data. I can't do anything but pray you don't throw an exception. Does anyone find this code acceptable?

if(thing.prayItDoesntFail()){
... continue on with logic
}else if(findSomePlaceRandom()){
gotoSomePlaceRandom();
}else{
die();
}

 And yet an unchecked exception is exactly that. If error, goto someplace  random up the stack and hope it gets caught somewhere. Really? I have to hope it gets resolved? Thats the answer? No, absolutely unaccecptable. If you have any idea that someting could fail then you should do your best to let me know, by making it checked. Anythign else is a lie. 

Mike P(Okidoky) replied on Thu, 2009/09/17 - 2:04pm

Actions, transactions, partial execution, artifacts.

The ideal way I think is to know when a job starts, gets to "try" to do its thing, and if it fails, the component that started the job, should be responsible for dealing with it. Problem is right now, that all kinds of sub components log and deal with errors inside a sub task burried deep down inside.

Exceptions should only *have* to be caught in methods marked as high-level of sorts (make up a name for it). The compiler should automatically collect all the possible exceptions and automatically mark methods as throwing everything that all the called methods can throw.

This way, in all the intermediate and low level code, you don't worry about catching exceptions. Only in that specially marked method you deal with it.

For example, in a gui application, when the user click a button, it could be the beginning of an action. A transactional object is created. The job begins. It sifts down in through a string of methods, and something could go wrong. None fo the methods worry about what they're throwing. Any method can throw whatever it wants (any exception it wants, let's not start throwings ints), and none of the low level methods worry about catching with anything. Something goes wrong, and the stack unwinds. All the stuff that has been done so far is all collected in this transactional object. The guy that started it, the code that listened for the user pressing the button, it is responsible to tellling that transactional object to undo what it did. Closing database connections, files, whatever. The user is prompted that him pressing the button caused an error and that the job could not be done. Everything is thrown out, and no damage (artifacts) are left behind all over the system. Nice and clean.

To make it work cleanly, it would be nice if there was a way to make things work in a transactional way. A bunch of stuff is attempted, and if something fails, none of the changes are seen by the outside world. Functional programming could be used for this. This way, the calculations and method calls could only ever return a result (or stuff the result in returned packages of objects). No artifacts, meaning, an exception at any part of the way, will not leave any damage around for the rest of the system.

So what I'm proposing:

  • Have the compiler automatically mark a method as throwing all the exceptions that all the called methods are marked as throwing.
  • (Optional) have a discipline keyword to force your lazy colleague to *have* to deal with all the possible exceptions.
  • Add functional programming / transactional features to the language. What that really means is way up in the air. I wonder if Scala's functional programming features can do anything like this...

I guess, ultimately, as a quick fix to a broken language, the first point would be very beneficial I think. The "transactional" / "functional programming" aspect of it, could be hand wrapped using created objects with calculation results, only ever published to the rest of the system if it completely completes.

 

Guido Amabili replied on Thu, 2009/09/17 - 2:52pm

Plus one for checked exceptions ......

This is a language feature. Period.

Thanks god, nobody at Sun ever thought to abolish checked exceptions,

those who want to use php or ruby or whatever do not hesitate please,

My opinion,

Guido

 

Marius Scurtescu replied on Thu, 2009/09/17 - 3:04pm

While I do find working with exceptions in general problematic, I disagree with most of the aruments presented here against checked exceptions.

 "The exceptions are used as away of informing us that we, as developers, have messed up.", really? This may be true in some ideal environment, but not in a real one with real world limitations. In many cases you can argue that exceptions can be folded into the return value, but that is the wrong approach IMO. For the exceptional cases now your code is more complicated and harder to read.

 "Checked exceptions force me to write catch blocks which are meaningless", your exception handling code is meaningless probably because you don't understand how you should write it and how it works. Logging and rethrowing in general is a really bad idea, do one or the other. If you rethrow, by wrapping the lower level exception into a higher level one then add conext information, this is crucial for troubleshooting or for higher code to take a decision. The arguments about noise and lost fidelity also boild down to the same thing, you have those problems because you are not using exceptions properly.

 "Unreachable code" , we should drop language features because of limitations in coverage tools or because you have this ideal of 100% coverage? C'mon. Improve your tools.

 You are saying that in most cases exceptions are bugs and recovery is not possible, well in my experience this is absolutely not true. Bug related exception in general are the unchecked ones, checked exception have nothing to do with bugs and in most cases you can recover from them.

 @migra, "Forcing a client to handle an Exception even if there is no way to handle it", how exactly are you forced to handle an exception? This is not true. Just declare your method that it throws that exception. In most cases even if you cannot handle an excetion you can (and should) add context information to it and then rethrow a higher level exception.

 @Greg, "Working with checked exceptions correctly, like working with concurrency is hard.", yes, but dropping checked exceptions based on this argument is like droping synchronization simply because it is hard to deal with. Just like for concurency, maybe the solution is some higher abstraction, but I haven't seen anything like that suggested for exceptions.

 

victor spivak replied on Thu, 2009/09/17 - 3:04pm

I could not disagree more.  Checked exceptions is the very useful facility. It allows programmers put proper error handling without checking documentation all the time.  I use JPA that does not use checked exceptions and I hate it. I saw on multiple occasions when a programmer forgot to properly handling NumberFormatException in the parseInt.

 Without checking exception it is so easy to break proper abstractions when low level code throws very specific exceptions and a higher level did not translate them in the proper abstractions.  Such problems is very difficult to find using unit testing.

The are bad examples of using checked exceptions. Granted. For instance, InputStream close method throws IOExcpetion.  How cold I handle it reasonably? Try to close second time? Such examples generate very negative impressions about checked exception.  We have to avoid such patterns and use checked exceptions only for cases when code could properly handle the exception situation.

I wouold recommend to add a couple more features in to javac. I would add an option to treat checked exceptions as unchecked.  It copuld be useful for prototyping when we less concern about code quality.  Also I would not treat catch an exception that is not throwing as an error (warning should be fine).  In this case we will be able to removechecked exception from method signature without breaking an existing code.

Hope that most of the good enginbeers will ignore the Misko suggestions. 

 

 

Mladen Girazovski replied on Thu, 2009/09/17 - 3:31pm

 @migra, "Forcing a client to handle an Exception even if there is no way to handle it", how exactly are you forced to handle an exception? This is not true. Just declare your method that it throws that exception. In most cases even if you cannot handle an excetion you can (and should) add context information to it and then rethrow a higher level exception.

 You force people to deal with checked exceptions, even if they cannot be handled the exception, so they have to pretend to deal with it, either by using try/catch or declaring a throws clause to that method.

There is an example of an IOException in this article that has to be handled,  nevermind the fact that it can never occure, leading to an empty catch block.

I'm sure you can deal very gracefully with SQLExceptions, right? ;)

 There is nothing you can't do with unchecked exceptions that you could do with checked exceptions , the opposite is not true.

If people do not write enough documentation for their code (especially the exceptions that could be thrown are important) they should not try to abuse checked exception to rectify the missing documentation.

On the other hand, you cannot force a developer to handle exceptions properly by using checked exceptions.If they are inept/unexpirienced/confused, checked exceptions won't help them. 

Your recommendation leads to broken encapsulation, you wouldn't wanna have all your higher level components to be aware (and thus dependent) of some Hibernate/iBatis/<insert any low level framework here> Exception, so you would have to translate the exception somewhere, there is no reason why you couldn't do exactly the same with unchecked exceptions.

This argument is imho boring, as i said before, the discussion unchecked vs. checked exceptions is over since years, checked exceptions were a mistake that has not been reproduced by any other language for good reasons.

Rich Hill replied on Thu, 2009/09/17 - 3:37pm

The battle over Checked Exceptions in Java has been around for a while, but there's really one major case that I think promotes Checked Exceptions more than anything else. FRAMEWORKS. Java has been undeniably successfully for the past decade and for the last 9 years of that, frameworks have lead the way. From Struts to Hibernate to Spring to all the good stuff from Apache, Java would be no where near as strong without frameworks. These external frameworks perform complicated actions in many cases and they have to be able to throw specific errors as a means of communicating errors. Being able to force the recognition and handling of these errors makes frameworks more stable and improves the code that uses them. I think that the proposed advanced error handling mechanism that just missed out as part of the project coin JDK 7 updates would be a far better solution for the generic error cases of catch..rethrow, catch..log, catch..log..rethrow. Checked exceptions should be reserved for those special cases where errors are dramatic and need to be handled. But then again, isn't that what an exceptional situation is by definition. Response on the Grabity Blog

Tim Boudreau replied on Thu, 2009/09/17 - 5:30pm

IMO the problem is that in a certain set of situations, checked exceptions make sense - for example, if you are modelling in software, say, a hardware device or wire protocol that has a set of well-defined failure modes (think LDAP/JNDI [almost twice as many exception classes as there are non-exception classes in API - monstrous!], for example), or where, if the exceptional state is unhandled, an airplane will crash.

But software being what it is, and Java being what it is, you end up with an of API that ends up being (ab)used well beyond its intended scope, where in fact those exceptions will never happen and don't make sense.  Inheritance being what it is, there is no way to convert a parent class's exceptions into unchecked exceptions.  So we end up with APIs full of checked exceptions because they're (ab)using or inheriting from something else that throws checked exceptions.

Think about it - there are plenty of exceptions that would be *useful* as checked exceptions some small part of the time (NumberFormatException, for example;  MalformedURLException if you're writing a web browser, but practically never otherwise).  The problem might be that the division of checked/unchecked is too rigid in Java, not that one is necessarily always preferable to the other.

-Tim

Marius Scurtescu replied on Thu, 2009/09/17 - 7:13pm

@mgira, don't get me wrong, I am not defending checked exception, all I am saying is that many of the arguments brought forth do not hold water IMO.

One thing that checked exceptions can do and unchecked cannot is to bring awareness. Unchecked exceptions are out of sight and out of mind, very unlikely you will write code to deal with them. It is extremely hard to deal with unchecked exceptions because you don't know where they are thrown. Even worse, some library you depend on my start throwing some unchecked exceptions after a library upgrade, now suddenly all code depending on it is potentially broken, and fixing is very complex (no compiler support for starters).

The argument with the unexperienced developer is invalid. If someone does not have the skills to deal with checked exceptions, how on earth will that person deal with the unchecked ones? Just ignoring the whole issue is not solving it.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.