Many people say that checked exceptions (i.e. these that you should explicitly catch or rethrow) should not be used at all. They were eliminated in C# for example, and most languages don't have them. So you can always throw a subclass of RuntimeException (unchecked exception).
However, I think checked exceptions are useful - they are used when you want to force the user of your API to think how to handle the exceptional situation (if it is recoverable). It's just that checked exceptions are overused in the Java platform, which makes people hate them.
Here's my extended view on the topic.
As for the particular questions:
Is the
NumberFormatExceptionconsidered a checked exception?
No.NumberFormatExceptionis unchecked (= is subclass ofRuntimeException). Why? I don't know. (but there should have been a methodisValidInteger(..))Is
RuntimeExceptionan unchecked exception?
Yes, exactly.What should I do here?
It depends on where this code is and what you want to happen. If it is in the UI layer - catch it and show a warning; if it's in the service layer - don't catch it at all - let it bubble. Just don't swallow the exception. If an exception occurs, in most of the cases, you should choose one of these:
- log it and return
- rethrow it (declare it to be thrown by the method)
- construct a new exception by passing the current one in constructor
Now, couldn't the above code also be a checked exception? I can try to recover the situation like this? Can I?
It could've been. But nothing stops you from catching the unchecked exception as well.Why do people add class
Exceptionin the throws clause?
Most often because people are lazy to consider what to catch and what to rethrow. ThrowingExceptionis a bad practice and should be avoided.
Alas, there is no single rule to let you determine when to catch, when to rethrow, when to use checked and when to use unchecked exceptions. I agree this causes much confusion and a lot of bad code. The general principle is stated by Bloch (you quoted a part of it). And the general principle is to rethrow an exception to the layer where you can handle it.
Answer from Bozho on Stack OverflowVideos
Many people say that checked exceptions (i.e. these that you should explicitly catch or rethrow) should not be used at all. They were eliminated in C# for example, and most languages don't have them. So you can always throw a subclass of RuntimeException (unchecked exception).
However, I think checked exceptions are useful - they are used when you want to force the user of your API to think how to handle the exceptional situation (if it is recoverable). It's just that checked exceptions are overused in the Java platform, which makes people hate them.
Here's my extended view on the topic.
As for the particular questions:
Is the
NumberFormatExceptionconsidered a checked exception?
No.NumberFormatExceptionis unchecked (= is subclass ofRuntimeException). Why? I don't know. (but there should have been a methodisValidInteger(..))Is
RuntimeExceptionan unchecked exception?
Yes, exactly.What should I do here?
It depends on where this code is and what you want to happen. If it is in the UI layer - catch it and show a warning; if it's in the service layer - don't catch it at all - let it bubble. Just don't swallow the exception. If an exception occurs, in most of the cases, you should choose one of these:
- log it and return
- rethrow it (declare it to be thrown by the method)
- construct a new exception by passing the current one in constructor
Now, couldn't the above code also be a checked exception? I can try to recover the situation like this? Can I?
It could've been. But nothing stops you from catching the unchecked exception as well.Why do people add class
Exceptionin the throws clause?
Most often because people are lazy to consider what to catch and what to rethrow. ThrowingExceptionis a bad practice and should be avoided.
Alas, there is no single rule to let you determine when to catch, when to rethrow, when to use checked and when to use unchecked exceptions. I agree this causes much confusion and a lot of bad code. The general principle is stated by Bloch (you quoted a part of it). And the general principle is to rethrow an exception to the layer where you can handle it.
Whether something is a "checked exception" has nothing to do with whether you catch it or what you do in the catch block. It's a property of exception classes. Anything that is a subclass of Exception except for RuntimeException and its subclasses is a checked exception.
The Java compiler forces you to either catch checked exceptions or declare them in the method signature. It was supposed to improve program safety, but the majority opinion seems to be that it's not worth the design problems it creates.
Why do they let the exception bubble up? Isnt handle error the sooner the better? Why bubble up?
Because that's the entire point of exceptions. Without this possibility, you would not need exceptions. They enable you to handle errors at a level you choose, rather than forcing you to deal with them in low-level methods where they originally occur.
Many a blog post has been written about how Checked Exception are bad/the devil incarnate.
For all the bloviating about how bad it is, most of these articles and their comment sections lack any concrete alternatives.
For Java versions before 21, there simply doesn't seem to be a reasonable (never mind close to standardized) alternative to express that a method returns Thing or AException or BException.
For Java 21+, with sealed classes and exhaustive switches, you kind of can manually recreate a vague resemblance of e.g. Rusts Result Type. That will still lack some necessities, like enforcing checking the Error for Void methods (as in Result<Void, Err>).
So my question is:
If you agree that checked exceptions are bad, what alternative are you actively using right now?
How is your favorite library handling this? Because most still seem to use exceptions
Personally, I'm getting reaaaallly annoyed by the way people talk about exceptions online. For one, they'll point out a problem, but then fail to demonstrate a solution that wouldn't have it. For another, there's very little will, it seems, to suggest and work towards a serious alternative. How can we, as a community, warn against using a builtin feature for an important part of programming without providing alternatives? Aren't we simply screwing over newbies with these takes?
First of all, like any other programming paradigm you need to do it right for it to work well.
For me the advantage of checked exceptions is that the authors of the Java runtime library ALREADY have decided for me what common problems I might reasonably be expected to be able to handle at the calling point (as opposed to a top-level catch-print-die block) and consider as early as possible how to handle these problems.
I like checked exceptions because they make my code more robust by forcing me to think about error recovery as early as possible.
To be more precise, to me this makes my code more robust as it forces me to consider strange corner cases very early in the process as opposed to saying "Oops, my code does not handle if the file doesn't exist yet" based on an error in production, which you then have to rework your code to handle. Adding error handling to existing code can be a non-trivial task - and hence expensive - when reaching maintenance as opposed to just doing it right from the start.
It might be that the missing file is a fatal thing and should cause the program to crash in flames, but then you make that decision with
} catch (FileNotFoundException e) {
throw new RuntimeException("Important file not present", e);
}
This also shows a very important side effect. If you wrap an exception, you can add an explanation which goes in the stack-trace! This is so extremely powerful because you can add information about e.g. the name of the file that was missing, or the parameters passed to this method or other diagnostic information, and that information is present right in the stack trace which frequently is the single thing you get when a program has crashed.
People may say "we can just run this in the debugger to reproduce", but I have found that very frequently production errors cannot be reproduced later, and we cannot run debuggers in production except for very nasty cases where essentially your job is at stake.
The more information in your stack trace, the better. Checked exceptions help me get that information in there, and early.
EDIT: This goes for library designers as well. One library I use on a daily basis contains many, many checked exceptions which could have been designed much better making it less tedious to use.
You've got two good answers which explain what checked exceptions have become in practice. (+1 to both.) But it would also be worthwhile to examine what they were intended for in theory, because the intention is actually worthwhile.
Checked exceptions are actually intended to make the language more type safe. Consider a simple method like integer multiplication. You might think that the result type of this method would be an integer, but, strictly speaking, the result is either an integer or an overflow exception. Considering the integer result by itself as the return type of the method does not express the full range of the function.
Seen in this light, it's not strictly true to say that checked exceptions have not found their way into other languages. They have just not taken the form that Java used. In Haskell applications, it is common to use algebraic data types to distinguish between successful and unsuccessful completion of the function. Although this is not an exception, per se, the intention is very much the same as a checked exception; it is an API designed to force the API consumer to handle both the successful in the unsuccessful case, e.g.:
data Foo a =
Success a
| DidNotWorkBecauseOfA
| DidNotWorkBecauseOfB
This tells the programmer that the function has two additional possible results besides success.
I do not know enough context to know whether your colleague is doing something incorrectly or not, so I am going to argue about this in a general sense.
I do not think it is always an incorrect practice to turn checked exceptions into some flavor of runtime exception. Checked exceptions are often misused and abused by developers.
It is very easy to use checked exceptions when they are not meant to be used (unrecoverable conditions, or even control flow). Especially if a checked exception is used for conditions from which the caller cannot recover, I think it is justified to turn that exception to a runtime exception with a helpful message/state. Unfortunately in many cases when one is faced with an unrecoverable condition, they tend to have an empty catch block which is one of the worst things you can do. Debugging such an issue is one of the biggest pains a developer can encounter.
So if you think that you are dealing with a recoverable condition, it should be handled accordingly and the exception should not be turned into a runtime exception. If a checked exception is used for unrecoverable conditions, turning it into a runtime exception is justified.
It can be GOOD. Please read this onjava.com article:
Most of the time, client code cannot do anything about SQLExceptions. Do not hesitate to convert them into unchecked exceptions. Consider the following piece of code:
public void dataAccessCode(){
try{
..some code that throws SQLException
}catch(SQLException ex){
ex.printStacktrace();
}
}
This catch block just suppresses the exception and does nothing. The justification is that there is nothing my client could do about an SQLException. How about dealing with it in the following manner?
public void dataAccessCode(){
try{
..some code that throws SQLException
}catch(SQLException ex){
throw new RuntimeException(ex);
}
}
This converts SQLException to RuntimeException. If SQLException occurs, the catch clause throws a new RuntimeException. The execution thread is suspended and the exception gets reported. However, I am not corrupting my business object layer with unnecessary exception handling, especially since it cannot do anything about an SQLException. If my catch needs the root exception cause, I can make use of the getCause() method available in all exception classes as of JDK1.4.
Throwing checked exceptions and not being able to recover from it is not helping.
Some people even think that checked exceptions should not be used at all. See http://www.ibm.com/developerworks/java/library/j-jtp05254/index.html
Recently, several well-regarded experts, including Bruce Eckel and Rod Johnson, have publicly stated that while they initially agreed completely with the orthodox position on checked exceptions, they've concluded that exclusive use of checked exceptions is not as good an idea as it appeared at first, and that checked exceptions have become a significant source of problems for many large projects. Eckel takes a more extreme view, suggesting that all exceptions should be unchecked; Johnson's view is more conservative, but still suggests that the orthodox preference for checked exceptions is excessive. (It's worth noting that the architects of C#, who almost certainly had plenty of experience using Java technology, chose to omit checked exceptions from the language design, making all exceptions unchecked exceptions. They did, however, leave room for an implementation of checked exceptions at a later time.)
Also from the same link:
The decision to use unchecked exceptions is a complicated one, and it's clear that there's no obvious answer. The Sun advice is to use them for nothing, the C# approach (which Eckel and others agree with) is to use them for everything. Others say, "there's a middle ground."