Why Catching Throwable or Error is bad? [duplicate] - java

Is it a bad practice to catch Throwable?
For example something like this:
try {
// Some code
} catch(Throwable e) {
// handle the exception
}
Is this a bad practice or we should be as specific as possible?

You need to be as specific as possible. Otherwise unforeseen bugs might creep away this way.
Besides, Throwable covers Error as well and that's usually no point of return. You don't want to catch/handle that, you want your program to die immediately so that you can fix it properly.

This is a bad idea. In fact, even catching Exception is usually a bad idea. Let's consider an example:
try {
inputNumber = NumberFormat.getInstance().formatNumber( getUserInput() );
} catch(Throwable e) {
inputNumber = 10; //Default, user did not enter valid number
}
Now, let's say that getUserInput() blocks for a while, and another thread stops your thread in the worst possible way ( it calls thread.stop() ). Your catch block will catch a ThreadDeath Error. This is super bad. The behavior of your code after catching that Exception is largely undefined.
A similar problem occurs with catching Exception. Maybe getUserInput() failed because of an InterruptException, or a permission denied exception while trying to log the results, or all sorts of other failures. You have no idea what went wrong, as because of that, you also have no idea how to fix the problem.
You have three better options:
1 -- Catch exactly the Exception(s) you know how to handle:
try {
inputNumber = NumberFormat.getInstance().formatNumber( getUserInput() );
} catch(ParseException e) {
inputNumber = 10; //Default, user did not enter valid number
}
2 -- Rethrow any exception you run into and don't know how to handle:
try {
doSomethingMysterious();
} catch(Exception e) {
log.error("Oh man, something bad and mysterious happened",e);
throw e;
}
3 -- Use a finally block so you don't have to remember to rethrow:
Resources r = null;
try {
r = allocateSomeResources();
doSomething(r);
} finally {
if(r!=null) cleanUpResources(r);
}

Also be aware that when you catch Throwable, you can also catch InterruptedException which requires a special treatment. See Dealing with InterruptedException for more details.
If you only want to catch unchecked exceptions, you might also consider this pattern
try {
...
} catch (RuntimeException exception) {
//do something
} catch (Error error) {
//do something
}
This way, when you modify your code and add a method call that can throw a checked exception, the compiler will remind you of that and then you can decide what to do for this case.

straight from the javadoc of the Error class (which recommends not to catch these):
* An <code>Error</code> is a subclass of <code>Throwable</code>
* that indicates serious problems that a reasonable application
* should not try to catch. Most such errors are abnormal conditions.
* The <code>ThreadDeath</code> error, though a "normal" condition,
* is also a subclass of <code>Error</code> because most applications
* should not try to catch it.
* A method is not required to declare in its <code>throws</code>
* clause any subclasses of <code>Error</code> that might be thrown
* during the execution of the method but not caught, since these
* errors are abnormal conditions that should never occur.
*
* #author Frank Yellin
* #version %I%, %G%
* #see java.lang.ThreadDeath
* #since JDK1.0

It's not a bad practice if you absolutely cannot have an exception bubble out of a method.
It's a bad practice if you really can't handle the exception. Better to add "throws" to the method signature than just catch and re-throw or, worse, wrap it in a RuntimeException and re-throw.

Catching Throwable is sometimes necessary if you are using libraries that throw Errors over-enthusiastically, otherwise your library may kill your application.
However, it would be best under these circumstances to specify only the specific errors thrown by the library, rather than all Throwables.

The question is a bit vague; are you asking "is it OK to catch Throwable", or "is it OK to catch a Throwable and not do anything"? Many people here answered the latter, but that's a side issue; 99% of the time you should not "consume" or discard the exception, whether you are catching Throwable or IOException or whatever.
If you propagate the exception, the answer (like the answer to so many questions) is "it depends". It depends on what you're doing with the exception—why you're catching it.
A good example of why you would want to catch Throwable is to provide some sort of cleanup if there is any error. For example in JDBC, if an error occurs during a transaction, you would want to roll back the transaction:
try {
…
} catch(final Throwable throwable) {
connection.rollback();
throw throwable;
}
Note that the exception is not discarded, but propagated.
But as a general policy, catching Throwable because you don't have a reason and are too lazy to see which specific exceptions are being thrown is poor form and a bad idea.

Throwable is the base class for all classes than can be thrown (not only exceptions). There is little you can do if you catch an OutOfMemoryError or KernelError (see When to catch java.lang.Error?)
catching Exceptions should be enough.

it depends on your logic or to be more specific to your options / possibilities. If there is any specific exception that you can possibly react on in a meaningful way, you could catch it first and do so.
If there isn't and you're sure you will do the same thing for all exceptions and errors (for example exit with an error-message), than it is not problem to catch the throwable.
Usually the first case holds and you wouldn't catch the throwable. But there still are plenty of cases where catching it works fine.

Although it is described as a very bad practice, you may sometimes find rare cases that it not only useful but also mandatory. Here are two examples.
In a web application where you must show a meaning full error page to user.
This code make sure this happens as it is a big try/catch around all your request handelers ( servlets, struts actions, or any controller ....)
try{
//run the code which handles user request.
}catch(Throwable ex){
LOG.error("Exception was thrown: {}", ex);
//redirect request to a error page.
}
}
As another example, consider you have a service class which serves fund transfer business. This method returns a TransferReceipt if transfer is done or NULL if it couldn't.
String FoundtransferService.doTransfer( fundtransferVO);
Now imaging you get a List of fund transfers from user and you must use above service to do them all.
for(FundTransferVO fundTransferVO : fundTransferVOList){
FoundtransferService.doTransfer( foundtransferVO);
}
But what will happen if any exception happens? You should not stop, as one transfer may have been success and one may not, you should keep go on through all user List, and show the result to each transfer. So you end up with this code.
for(FundTransferVO fundTransferVO : fundTransferVOList){
FoundtransferService.doTransfer( foundtransferVO);
}catch(Throwable ex){
LOG.error("The transfer for {} failed due the error {}", foundtransferVO, ex);
}
}
You can browse lots of open source projects to see that the throwable is really cached and handled. For example here is a search of tomcat,struts2 and primefaces:
https://github.com/apache/tomcat/search?utf8=%E2%9C%93&q=catch%28Throwable
https://github.com/apache/struts/search?utf8=%E2%9C%93&q=catch%28Throwable
https://github.com/primefaces/primefaces/search?utf8=%E2%9C%93&q=catch%28Throwable

Generally speaking you want to avoid catching Errors but I can think of (at least) two specific cases where it's appropriate to do so:
You want to shut down the application in response to errors, especially AssertionError which is otherwise harmless.
Are you implementing a thread-pooling mechanism similar to ExecutorService.submit() that requires you to forward exceptions back to the user so they can handle it.

Throwable is the superclass of all the errors and excetions.
If you use Throwable in a catch clause, it will not only catch all exceptions, it will also catch all errors. Errors are thrown by the JVM to indicate serious problems that are not intended to be handled by an application. Typical examples for that are the OutOfMemoryError or the StackOverflowError. Both are caused by situations that are outside of the control of the application and can’t be handled. So you shouldn't catch Throwables unless your are pretty confident that it will only be an exception reside inside Throwable.

If we use throwable, then it covers Error as well and that's it.
Example.
public class ExceptionTest {
/**
* #param args
*/
public static void m1() {
int i = 10;
int j = 0;
try {
int k = i / j;
System.out.println(k);
} catch (Throwable th) {
th.printStackTrace();
}
}
public static void main(String[] args) {
m1();
}
}
Output:
java.lang.ArithmeticException: / by zero
at com.infy.test.ExceptionTest.m1(ExceptionTest.java:12)
at com.infy.test.ExceptionTest.main(ExceptionTest.java:25)

A more differentiated answer would be: it depends.
The difference between an Exception and an Error is that an Exception is a state that has to be expected, while an Error is an unexpected state, which is usually fatal. Errors usually cannot be recovered from and require resetting major parts of the program or even the whole JVM.
Catching Exceptions is something you should always do to handle states that are likely to happen, which is why it is enforced by the JVM. I.E. opening a file can cause a FileNotFoundException, calling a web resource can result in a TimeoutException, and so on. Your code needs to be prepared to handle those situations as they can commonly occur. How you handle those is up to you, there is no need to recover from everything, but your application should not boot back to desktop just because a web-server took a little longer to answer.
Catching Errors is something you should do only if it is really necessary. Generally you cannot recover from Errors and should not try to, unless you have a good reason to. Reasons to catch Errors are to close critical resources that would otherwise be left open, or if you i.E. have a server that runs plugins, which can then stop or restart the plugin that caused the error. Other reasons are to log additional information that might help to debug that error later, in which case you of course should rethrow it to make sure the application terminates properly.
Rule of thumb: Unless you have an important reason to catch Errors, don't.
Therefore use catch (Throwable t) only in such really important situation, otherwise stick to catch (Exception e)

Related

Catching throwable and handling specific exceptions

Ok I know catching throwable is not a good idea:
try {
// Some code
} catch(Throwable e) { // Not cool!
// handle the exception
}
But recently I was reading through an open sourced code and I saw this interesting (at least to me) piece of code:
try {
// Some Code
} catch (Throwable ex){
response = handleException(ex, resource);
}
private handleException(Throwable t, String resource) {
if (t instanceof SQLEXception) {
// Some code
} else if (t instanceof IllegalArgumentException) {
//some code
} //so on and so forth
}
This doesn't seem to be that bad? What is wrong with this approach?
There are various reasons why you should not catch a Throwable. First of all is, that Throwable includes Errors - and there's normally not much an application can do if one of these appears. Also Throwable reduces your chances of finding out, WHAT has happened. All you get is "something bad has happened" - which might be a catastrophe or just a nuisance.
The other aproach is better but of course I still would not catch Throwable, but try to catch more specific Exceptions, if possible at all. Otherwise you are catching everything and then try to sort out which kind of bad thing happened. Your example could be written as...
try {
...
} catch (SQLEXception ex){
response = ... ;
} catch (IllegalArgumentException ex){
response = ...;
}
...which would reduce the amount of if ( ... instanceof ... ) blocks (which are only needed because the author first decided to catch everything in one big bucket). It something actually throws Throwable, then you don't have much choice, of course.
You are right when you say that catching Throwable is not a good idea. However, the code that you present in your question is not catching Throwable in an evil way but let's talk about that later. For now, the code that you present in your question has several advantages :
1. Readability
If you look at the code carefully, you will notice that even though the catch block is catching a Throwable, the handleException method is checking the type of exception thrown and possibly taking different actions based on the exception type.
The code presented in your question is synonymous to saying:
try {
doSomething();
} catch (SQLEXception ex){
response = handleException(resource);
} catch(IllegalArgumentException ex) {
response = handleException(resource);
} catch(Throwable ex) {
response = handleException(resource);
}
Even if you have to catch 10+ exceptions only, this code can easily take up a lot of lines of code and the multi-catch construct is not going to make the code any cleaner. The code that you present in your question is simply delegating the catch to another method to make the actual method that does the work more readable.
2. Reusability
The code for the handleRequest method could easily be modified and placed in a utility class and accessed throughout your application to handle both Exceptions and Errors. You could even extract the method into two private methods; One that handles Exception and one that handles Error and have the handleException method that takes a Throwable further delegate the calls to these methods.
3. Maintainibility
If you decide that you want to change the way you log an SQLExceptions in your application, you have to make this change in a single place rather than visiting every method in every class that throws an SQLException.
So is catching Throwable a bad idea?
The code that you present in your question is not really the same as catching Throwable alone. The following piece of code is a big no-no:
try {
doSomething();
} catch(Throwable e) {
//log, rethrow or take some action
}
You should catch Throwable or Exception as far away in the catch chain as possible.
Last but not the least, remember that the code you present in your question is framework's code and there are certain errors that the framework can still recover from. See When to catch java.lang.Error for a better explanation.
Catching Throwables out of laziness is a bad idea.
This was particularly tempting before try-multi-catch was introduced.
try {
...
} catch (SomeException e) {
//do something
} catch (OtherException e) {
//do the same thing
} ...
Repeating catch blocks is tedious and verbose, so some people decided to just catch Exception or Throwable and be done with it. This is what should be avoided because:
It makes it difficult to follow what you're trying to do.
You may end up catching a lot of stuff you can't deal with.
You deserve bonus punishment if you completely swallow the Throwable in the catch block. (And we've all seen code that does that...:))
But catching Throwables when it is absolutely necessary is fine.
When is it necessary? Very rarely. In framework-style code there are various scenarios (dynamically loading an external class is the most obvious one), in a standalone application a typical example is to attempt to display/log some kind of error message before exiting. (Bearing in mind that the attempt may fail, so you don't want to put anything critical there.)
As a rule of thumb, if there's nothing you can do about an exception/error, you shouldn't catch it at all.
You posted a link to Jongo, which demonstrates one possible use for this technique: re-using error handling code.
Let's say you've got a large block of error handling code that naturally repeats itself in various places in your code - for example Jongo produces standard responses for some standard classes of errors. It may be a good idea to extract that error handling code into a method, so you can re-use it from all the places it's needed.
However, that's not to say that there's nothing wrong with Jongo's code.
Catching Throwable (rather than using multicatch) is still suspicious, as you're likely to catch Errors that you're not really in a position to handle (are you sure you meant to catch ThreadDeath?). In this situation, if you absolutely have to catch Throwable, it'd be better to "catch and release" (i.e, rethrow anything that you didn't mean to catch). Jongo doesn't do this.
There are exactly two valid uses for using a huge net:
If you will handle everything uniformly, like a top-level catch for logging/reporting, possibly followed by an immediate exit.
To reduce duplication, by exporting all the handling into its own method.
Catch the most derived common ancestor there is to avoid extra-work and increase clarity.
DRY is an important design principle.
In both cases, unless you expected that exception and handled it completely, rethrow.
First of all, catching Throwable makes your application rather intransparent. You should be as explicit as possible on catching exceptions to enable good traceability in exceptional cases.
Let's have a look at the method handleException(...) and see some of the problems that occur by this approach:
you catch Throwable but you only handle Exceptions, what happens if an e.g. OutOfMemoryError of type Error is thrown? - I see bad things to happen...
Regarding good object oriented programming using instanceof breaks the Open-Closed-Principle and makes code changes (e.g. adding new exceptions) really messy.
From my point of view, catch-blocks are exactly made for the functionality that are tried to cover in handleExceptions(...), so use them.
Java 7 solves a bit of the tedium that is multi-catching of similar exceptions with similar handling. You definitely should not be doing what the person has done here. Just catch the appropriate exceptions as needed, it may look ugly but then that's what throws is for, pass it to the method that should catch it and you shouldn't be wasting too much code space.
Check out this link for more information.
Just to provide balance - there is one place where I will always catch (Throwable):
public static void main(String args[]) {
try {
new Test().test();
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
At least something shows somewhere that something went wrong.
You can always catch different type of exceptions and perform some operations based on the type of the exception you got.
Here is an example
try{
//do something that could throw an exception
}catch (ConnectException e) {
//do something related to connection
} catch (InvalidAttributeValueException e) {
// do anything related to invalid attribute exception
} catch (NullPointerException e) {
// do something if a null if obtained
}
catch (Exception e) {
// any other exception that is not handled can be catch here, handle it here
}
finally{
//perform the final operatin like closing the connections etc.
}

If RuntimeException is thrown, can it be caught as an Exception?

If I have a try block that throws a RuntimException subclass, can a subsequent catch block catches it as an Exception? Specifically:
public class MyAppException extends RuntimeException {
// ....
}
// In some other part of the code:
try {
// Executing this results with doSomething() throwing a MyAppException.
int x = doSomething();
} catch(Exception exc) {
// Does the thrown MyAppException get caught here?
}
My thinking is yes, because a RuntimeException extends Exception. However I have some production code that is not behaving this way. So obviously, if the answer is no, then that's my answer; otherwise I need to dig down and see why my code is breaking bad. Thanks in advance!
RuntimeException is derived from Exception, so it will get caught.
Having said this, don't do it! Runtime exceptions should be prevented, not caught.
Yes. It will catch RuntimeExceptionbut in case any Exception arise in catch block that you have to catch again.
I would suggest you to make a local deployment and debug the code.
If catch(Exception) is not catching your RuntimeException then your application is not behaving the way you think.
try {
throw new RuntimeException();
} catch (Exception e) {
System.out.println("Caught "+e);
}
prints
Caught java.lang.RuntimeException
Yes. It is possible to catch RuntimeExceptions.
All subclasses of Throwable can be caught.
Yes , you can catch RuntimeException...But i think its not a good approach, if you catch it you should properly manage it. Otherwise the result is out of your hand. Best way is to leave it to JVM . JVM will handle it.
Yes, your thinking is correct, I think the best way to know answer to "just writing the code", let the code tell you the answer. you can see the following simple example code:
package own;
public class MyExceptionTest {
public void testRuntimeException (){
throw new MyException();
}
public static void main(String[] args) {
try{
new MyExceptionTest().testRuntimeException();
}catch(Exception e){
System.out.println(e.getClass().getName());
}
}
}
class MyException extends RuntimeException{
public MyException(){
super();
}
}
I am a project manager in IT and I have had the same argument over and over with my devs and they simply dont care. Browsing the net, even most people advocate catching and throwing RuntimException... Every time I see it I get unbelievably furious about the inaptitude after 10 years of experience....
Rule No.1:
Never ever throw a runtimeexception in Program if you didnt catch a RuntimeException.
Rule No.2:
Only catch a Runtimeexception in order to some really import stuff that has nothing to do with your software: e.g. send a mail to operations emergency shift, log exception, restart the server....
The reason for this is that in good software there is no stacktrace in a logfile. When feel uncomfortable starting to code do this:
Create new class DevelopmentException Extends Exception.
Then goahead and write your code and catch for exception initially. Then you rethrow it as your very own developmentexception. In the method catching it you log it.
Now: Everyday grep for your very personal DevelopmentException. If you find one this means there is still work to do. Go into your code and see where the Exception came from and catch it beforehand.
Ideally you will never see a DevelopmentException in this part of your program again. Repeat until there are 0 Stacktraces in your Software left and you have perfected Exception handling.
The biggest issue with throwing and catching runtime exception is that the compile ignores it. So this means when one of your colleagues writes a booking interface and throws RuntimeException when there is a value missing (yeah, ppl really do)... ...the compiler will not show you that there might be a runtimeexception. Now, when you dont catch it then your program might just shut down without any logging.
Why is it called RuntimeException?
Many mistake this for Error during Runtime of Program, however it actually means 'An Exception so utterly destructive that the Java Runtime Environment need to be stoppep'. In other words it meand: OutOfMemory, BrokenRam, FaultyImplementation of JRE, etc... basically stuff that tell you: Program cannot run because PC is crashing....
Just my 2 cents.
Anyone experienced the same stuff?
PS: Regarding continous removal of stacktraces:
Once you see an exception try to catch it with e.g. NullpointerException.
When you see Nullpointerexception go to your code and remove the stacktrace, and just log.WARN(NullpointerOccured) and write your Program to retry or so...
Ideally you repeat until you never see a Stacktrace again.
When you cannot see a stacktrace ever it means all that could possibly go wrong is taken care of (Except for RuntimeException of course)

Throwing checked exception in Java

Let's say I am designing an API for storing passwords. According to Effective Java it is a good idea to use throw clauses to show checked exceptions, however by having a throw clause that throws a SQLException, which is a checked exception, then I am revealing the underlying implementation details of my API and thus I will be unable to change the implementation details of my API at a later stage. One of the pros to throwing a checked exception is that the programmer who uses the API should be able to handle the exception in a manner of their choosing. Which of these two methods should I choose to do, add a throw clause which reveals the implementation or hide it or use a different approach?
Your motivation is correct for not "leaking" SQLException to the users of your class.
The fact that you're using SQL could be considered an implementation detail. You may even swap SQL persistence for say, an in-memory one at a later time, and this change shouldn't impact the users of your class.
If you are inclined to use checked exceptions, I would define your own exception type (say, PasswordStoreException -- just an example name). You can use it to wrap the original exception that was thrown, e.g.:
try {
// do whatever
} catch (SQLException ex) {
throw new PasswordStoreException(ex);
}
It is today considered bad design for an API to declare checked exceptions. If you have ever used such an API, you should already know why.
In any case your API should never throw (let alone declare) exceptions belonging to other APIs. If you do that, you hang a completely unrelated dependency on your client's back. The only "exception" to this rule are JDK's standard exceptions like NPE, ISE and the like.
Catch the SQLException, and wrap it into your own exception:
try {
// JDBC code
}
catch (SQLException e) {
throw new MyException("Error persisting the secret", e); // choose a better name, of course
}
Whether this exception should be a checked exception or a runtime exception depends on what the caller can do about it. If it's recoverable (which, I think, is not the case here), it should be a checked exception. If it's not recoverable (the caller can just display an error message), then it should be a runtime exception.
If it's a checked exception, you have no choice; the exception MUST be declared in the throws clause of the method.
As is, it is always a good idea to throw your own exception checked/unchecked. But before that, try to fix the underlying exception if possible. I always prefer the below way,
try {
// JDBC code
}
catch (SQLException e) {
// try to solve the exception at API level
bollean solvable = trySolveException(e);
if (!solvable) {
// Alert the admin, or log the error statement for further debugging.
mailClient.sendMailToDBAdmin("Some issue storing password", e);
// or
LOG.severe("some issue in storing password " + e.toString);
throw MyException("A request/logstatement is logged on your behalf regarding the exception", e);
}
LOG.info("The exception is solved");
}
finally {
// don't forget to free your resources - to avoid garbage and memory leaks, incase you have solved the issue in trySolveException(e).
}
So,
1) You don't expose the SRQException directly, but you throw your own version of the exception.
2) You tried to solve the exception once and if not you alerted somehow - through a mail or a log statement.
3) Finally, you ve released all the resources if you succeed in solving the exception.
The finally clause can be avoided if you use the new Java7's try with resource close option.
For whether to throw checked or unchecked exception, I will give you an example
1) Say an exceptions like NPE - they are programmatic errors and the developer should be more responsible to have not created a NullPointer. You don't expect your code to account for such careless errors and put a try(NPE), catch(NPE). So throw a unchecked exceptions.
2) On the other hand the exceptions like SQL exceptions are at the rare cases, account for some external dependency. So, better throw a user defined checked exceptions. And the user can determine if he can connect to the backup SQL server if any.
3) There are another clause of exceptions, where the program cannot continue furhter. Say a Memory Out of Bounds. They should be thrown as Errors.
Try this..
fillInStackTrace() method is called to re-initialize the stack trace data in the newly created throwable. Will be helpful in masking the info about the exception when tries to access the API.

How can I handle user defined exceptions and after handling them resume the flow of program

/**
* An exception thrown when an illegal side pit was
* specified (i.e. not in the range 1-6) for a move
*/
public class IllegalSidePitNumException extends RuntimeException
{
/**
* Exception constructor.
* #param sidePitNum the illegal side pit that was selected.
*/
public IllegalSidePitNumException(int sidePitNum)
{
super("No such side pit number: "+sidePitNum);
}
}
How do I use this in a program and then resume for there? I do not want the program to end but want to handle the exception and continue.
You need to use try/catch. You can learn a lot about exception handling from Sun's (Oracle's) exception handling tutorials. In that tutorial look at the sections about Catching and Handling that specific address your question.
For example, in the code that calls the method that may throw this exception:
try {
...call method here...
} catch (IllegalSidePitNumException e) {
// Display message (per your comment to BalusC)
System.err.println(e.getMessage());
e.printStackTrace(System.err);
// You can also handle the exception other ways (but do not ignore it)
// Such as correcting some offending values, setting up for a retry
// logging the information, throwing a different exception
}
...program continues executing here...
Just catch it.
try {
doStuffWhichPossiblyThrowsThisException();
} catch (IllegalSidePitNumException e) {
// Don't rethrow it. I would however log it.
}
continueWithOtherStuff();
Sidenote: If this is an "expected" exception, you might want to inherit it from Exception instead of RuntimeException. RuntimeExceptions are intended to be used when something unexpected happens, for example illegal input due to a programmer error.
Of course, you don't give the context where you intend to use the exception so this is all theory (but you do mention that you want to continue the execution).
As others have said, you can do the following:
try {
doSomething();
} catch (SomeException ex) {
doRecovery();
}
doSomethingElse();
But there is no way to do something like the following in Java:
doSomething();
throw new SomeException(...);
doSomethingElse(); // ... after some handler has "resumed" the exception.
The above is a (hypothetical) example of "resumption model" exception handling, and Java does not support this. (Nor does C#, C++ or any other currently popular programming language ... though a couple of historical languages did support it.) In fact, the Java compiler will give you a compilation error for the above, saying that the statements after the throw are unreachable.

Java coding practice, runtime exceptions and this scenario

In the following scenario, I was trying to see how to handle this code and it how it relates to Runtimexception. I have read that is generally better to throw runtime exceptions as opposed to rely on static exceptions. And maybe even better to catch a static checked exception and throw an unchecked exception.
Are there any scenarios where it is OK to catch a static exception, possibly the catch-all Exception and just handle the exception. Possibly log an error message and continue on.
In the code below, in the execute1 method and execute2 method, let us say there is volatile code, do you catch the static exception and then rethrow? Or possibly if there are other errors:
if (null == someObj) { throw new RuntimeException(); }
Is this an approach you use?
Pseudo Code:
public class SomeWorkerObject {
private String field1 = "";
private String field2 = "";
public setField1() { }
public setField2() { }
// Do I throw runtime exception here?
public execute1() {
try {
// Do something with field 1
// Do something with field 2
} catch(SomeException) {
throw new RuntimeException();
}
}
// Do I throw runtime exception here?
public execute2() {
try {
// Do something with field 1
// Do something with field 2
} catch(SomeException) {
throw new RuntimeException();
}
}
}
public class TheWeb {
public void processWebRequest() {
SomeWorkerObject obj = new SomeWorkerObject();
obj.setField1("something");
obj.setField2("something");
obj.execute1();
obj.execute2();
// Possibility that runtime exception thrown?
doSomethingWith(obj);
}
}
I have a couple of problems with this code. There are times when I don't want a runtimeexception to be thrown because then execution stops in the calling method. It seems if I trap the errors in the method, maybe I can continue. But I will know if I can continue later on the program.
In the example above, what if obj.execute1() throws a Runtimeexception, then the code exits?
Edited: This guy seems to answer a lot of my questions, but I still want to hear your opinions.
http://misko.hevery.com/2009/09/16/checked-exceptions-i-love-you-but-you-have-to-go/
"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."
When catching an exception and throwing RuntimeException instead, it is important to set the original exception as a cause for the RuntimeException. i.e.
throw new RuntimeException(originalException).
Otherwise you will not know what was the problem in the first place.
Rethrowing checked exceptions as unchecked exceptions should only be done if you are sure that the checked exception is not to be expected.
Here's a typical example:
try {
hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
} catch (NoSuchAlgorithmException e) {
// Unexpected exception. "MD5" is just hardcoded and supported.
throw new RuntimeException("MD5 should be supported?", e);
} catch (UnsupportedEncodingException e) {
// Unexpected exception. "UTF-8" is just hardcoded and supported.
throw new RuntimeException("UTF-8 should be supported?", e);
}
There are times when I don't want a
runtimeexception to be thrown because
then execution stops in the calling
method. It seems if I trap the errors
in the method, maybe I can continue.
But I will know if I can continue
later on the program.
You have the right idea. The advice about throwing RuntimeException is that it doesn't require the caller to use a try-block or a 'throws' clause.
If your code can recover from an exception than it really should catch it and not throw anything.
One of the first rules about exceptions is to not abuse them to pass state in your application. They should be used for exceptional situations, not as alternative return values.
The second rule is to catch exceptions at the level you process them. Catch and rethrow does not add much. Any cleanup code in your method should be done in a finally block.
In my opinion catching checked exceptions and rethrowing them as runtime exceptions is abusing the system. It feels like working around the "limitations" of design by contract instead of using those "limitations" to get a more robust application.
Whether or not to handle an exception or simply rethrow it depends on your use case.
For example, if you're reading a file to load data into your application, and some IO error occurs, you're unlikely to recover from the error, so rethrowing the error to the top and consequently terminating the application isn't a bad course of action.
Conversely, if you're anticipating recoverable errors then you should absolutely catch and handle the errors. For example, you may have users entering data in a form. If they enter data incorrectly, your input processing code may throw an exception (e.g. NumberFormatException when parsing a malformed number string). Your code should catch these exceptions and return an error the user, prompting for correct input.
On an additional note, it's probably bad form to wrap all your exceptions with RuntimeException. If your code is going to be reused somewhere else, it is very helpful to have checked exceptions to signify that your code can fail in certain ways.
For example, assume your code is to parse configuration data from a file. Obviously, an IO error may occur, so you will have to catch an IOException somewhere in your code. You probably won't be able to do anything about the error, so you will have to rethrow it. However, someone calling into your code may well be able to handle such an error, for example by backing off to configuration defaults if the configuration can't be loaded from the file. By marking your API with checked exceptions, someone using your code can clearly see where an error may occur, and can thus write the error handling code at the appropriate place. If instead you simply throw a RuntimeException, the developer using your code won't be aware of possible errors until they creep up during testing.

Categories

Resources