11

I wrote the following code recently; it uses a lot of exception handling. I think it makes the code look very unreadable. I could shorten the code by catching generic exception, such as

catch (Exception e){ e.printStackTrace(); } 

but I also heard that catching generic exception is not a good coding practice.

public class DataAnalyzerTester { /** * @param args args[0] stores the filename * @exception NoSuchElementException if user attempts to access empty list element * @exception ArithmeticException if user attempts to divide by 0 * @exception ArrayIndexOutOfBoundsException if user supplied less than 3 arguments * @exception IOException problems with creating and writing files * @exception RuntimeException if user attempts to pass empty list to constructor */ public static void main(String[] args) { try{ //some code } catch (NoSuchElementException e) { System.out.println("Accessing element that does not exist: " + e.toString()); } catch (ArithmeticException e) { System.out.println("Division by zero: " + e.toString()); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Please supply a command line arguement that specifies your file path: " + e.toString()); } catch (IOException e) { System.out.println("Other IO errors: " + e.toString()); } catch (RuntimeException e) { System.out.println(e.toString()); } } } 

I would like to know if there is any better and cleaner way to catch multiple exceptions.

3
  • Your question appears to be asking for a one-size-fits-all solution where I don't think one exists. The exception handling specifics will depend on the needs and the structure of the program itself. Commented Sep 13, 2015 at 0:56
  • Well I would say you catch a general exception then use if statements to determine which exception is which and do corresponding things. That way you just need one catch. (If that is what you want) Commented Sep 13, 2015 at 1:00
  • 1
    A good article on the subject: stackify.com/best-practices-exceptions-java Commented May 9, 2019 at 10:49

2 Answers 2

23

First, unless you have very good reason, never catch RuntimeException, Exception or Throwable. These will catch most anything that is thrown, and Throwable will catch everything, even those things you're not meant to catch, like OutOfMemoryError.

Second, avoid catching runtime exceptions unless it directly impedes with the critical operation of your program. (But seriously, if anyone sees you catch a NullPointerException, they are within their full rights to call you out on it.) The only exceptions you should be bothering with are those that you are required to handle. Out of your list of exceptions, the only one you should bother with is IOException. The rest are the result of not enough tests, or sloppy coding; those shouldn't occur in the normal run time of your application.

Third, in Java 7, you have the ability to do a multi-catch statement for your exceptions, if the exceptions are mutually exclusive. The example linked does a good job of explaining it, but if you were to encounter code that threw both an IOException and an SQLException, you could handle it like this:

try { // Dodgy database code here catch (IOException|SQLException ex) { logger.log(ex); throw ex; } 

This cleans things up a bit, as you don't have unwieldy and huge chains of exceptions to catch.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for clearing things up for me. I completely agree with you. It seems like I rely on exceptions way too much. Things like ArrayIndexOutOfBoundsException and NoSuchElementException, I shouldn't rely on exceptions to do the job..
Discouraging people from using catch at high level doesn't seem very good IMO. We should encourage people to understand exceptions rather than ignoring them. And your "very good reason" is quite exaggerated, you normally only log on exceptions anyway, and at some level you very likely always want to log if you've caught an unexpected exception at least and we shouldn't tell people it's bad practice to do so. Catching throwable is bad, I give you that, but catching RuntimeException I would expect to see often.
"Log and throw" is questionable practice as it leads to duplicated logging on multiple levels.
One should never "log and rethrow"
19

First of all the problem with "best practice" advice is that it tends to over-simplify the question and the answer. Then someone (like yourself) comes along and notices that it is contradictory1.

IMO, best practice is to take "best practice" advice and people who regularly use that phrase with a healthy level of suspicion. Try to understand the real issues yourself, and reach your own conclusions ... rather than just relying someone else to tell you what is "best practice".

1 - Or worse ... they don't notice the contradictions, edge-cases, etc, and blindly follow the so-called "best practice". And occasionally, they find themselves in a dark place, because the "best practice" recommendation was inappropriate.


So what's the problem here? It is this statement:

but I also heard that catching generic exception is not a good coding practice.

In fact, it is not normally good coding practice to catch generic exceptions like Exception. But it is the right thing to do in some circumstances. And your example is one where it is appropriate.

Why?

Well lets look a case where catching Exception is a bad idea:

 public void doSomething(...) { try { doSomethingElse(...); } catch (Exception ex) { // log it ... and continue } } 

Why is that a bad idea? Because that catch is going to catch and handle unexpected exceptions; i.e. exceptions that you (the developer) did not think were possible, or that you did not even consider. That's OK ... but then the code logs the exception, and continues running as if nothing happened.

That's the real problem ... attempting to recover from an unexpected exception.

The (so-called) "best practice" advice to "never catch generic exceptions" deals with the issue, but in a crude way that doesn't deal with the edge cases. One of the edge cases is that catching (and logging) a generic exception is OK if you then immediately shut the application down ... like you are doing.

 public void main(...) { try { // ... } catch (Exception ex) { // log exception System.err.println("Fatal error; see log file"); System.exit(1); } } 

Now contrast that with the (supposedly) good practice version in your question. What is the difference?

  1. Your version produces more user friendly / less alarming diagnostics ... up to a point.
  2. Your version is significantly more code.
  3. Your version is unhelpful to someone trying to diagnose the problem because the stacktraces are not recorded.

And the counterpoints to 1 and 2 are:

  1. You can spend limitless time honing the "user friendly" diagnostics for an application, and still fail to help the kind of user who can't or won't understand ...
  2. It also depends on who the typical user is.

As you can see, this is far more nuanced than "catching generic exceptions is bad practice".

6 Comments

Catching generic exceptions is only a good practice when doing an exception hierarchy that is expected catch everything except errors. For example, going from the most specific exceptions to less specific, and finally Exception. But in all cases, it is possibly an information losing option. The more specific exception may carry detail that the general Exception class does not. At that point you have lost the information that might help someone doing failure analysis.
It depends on the context whether you should do that. And someone who is doing failure analysis is best served if you just give them the complete stacktrace ... and don't complicate the code with "helpful" stuff that might obscure the real problem.
If you ask an engineer, e.g. an EE, he will tell you there is no such thing as 'best practice'. there is only the best solution for the task at hand, which depends on a myriad of budgets: price, cost, power consumption, size, required lifetime, ... a constellation of factors which may never arise again in your career.
... or which you have never yet encountered in your career so far. Also read this: satisfice.com/blog/archives/27 ...
Worthy explanation. We can all get caught using "best practices" when we really don't want to take time to understand.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.