Is there any downside to always capturing Exception and not something more specific?

Asked

Viewed 3,667 times

81

When I write code in Java and try to treat exceptions I usually simply use the superclass Exception, not linking to the specific class and it usually works. There is some inconvenience in doing this?

try{
    Integer i = Integer.parseInt("3")
} catch(Exception e){ //em vez de NumberFormatException

}

5 answers

66


Generally speaking, it makes no sense for you to capture an exception if you don’t intend to treat it. Ideally let it "bubble up" (Bubble) for the same calling code, until some method is found that is actually able to treat it.

Java has these "checked exceptions" (checked exceptions), that force you to either treat or declare on signing the method that you can launch them. Because of this, many people end up doing things like:

catch(Exception e) {
    throw new RuntimeException(e);
}

To not have to declare "throws it", "throws it" in all that method. This is not good practice, because in the end the error messages that are printed on the console/logged in file become unnecessarily large and confusing - this when they are not truncated...

If you have a code "top-level" - type the method main, or the run of a thread, or a listener (Event Listener) Swing, etc - that can’t make exceptions no way, there is no problem in my opinion in using a catch generic, if your only action possible at that time is to log/print the error and abort the execution. Otherwise, prefer to capture the specific exception you will treat. If you intend to treat a set of exceptions in the same way, it is also okay to capture your more general type.

But if you want to give a "custom" treatment for an exception - let’s say "sign in with a number" when you find a NumberFormatException - use catch Exception may end up masking another error that has nothing to do, leaving the user angry by the program complaining of the format when its input is correct, and making debugging more difficult because the real cause of the exception is lost (if you let it bubble, at least it will be printed/logged at the end).

  • 1

    Could define "bubbling"?

  • 3

    @Patrick I say that the exception bubbles when it does not stop in that method, but rises to the calling method. Potentially rising to the caller’s caller, and so on, until she is treated or arrives at the top level.

  • 1

    Usually, I have nowhere to let more bubbling. I have k try not to let the program stop, simply. Thanks for the clarification

33

Much of what I could answer here can be found in the answer How to best treat exceptions in Java?. There are several links for other answers that if read together gives a good understanding of the problem that exception treatment has become in programming (I know, it is a lot but it is of utmost importance to understand the subject). Although some links not referring to Java the general idea is the same.

The first thing you should ask yourself is what do you gain by capturing the Exception. Why do you do this? There must be a reason. Is it used to bring better results? Either it’s used because it seems easier, or because a lot of people do it this way?

I imagine you know that an exception should never be "swallowed". In your example this happens but I believe it is just a simplified example. If you didn’t know this, maybe this is the most important new information for you post. Let’s see the example with an action on catch, so the exception NumberFormatException is not completely swallowed (although the action performed in the catch does not help much in real case):

try {
    Integer i = Integer.parseInt("3")
} catch(Exception e){ //em vez de NumberFormatException
    System.out.println("Número inválido");
}

I put in the Github for future reference.

Is the problem solved? The swallowing exception? No! And worse, you’re not even realizing you’re swallowing exceptions. Swallow it by accident. If there is a memory allocation error your application will break saying that there was a Número inválido. And you’ll wonder why the hell that happened. You swallowed all the other possible exceptions. You captured every possible exception and gave treatment to only one of them.

And if you give the treatment to all of them, you solve it? It may seem so. Is that what you want to do? In a simple problem, do you want to worry about any possible exception? Can you know all of them? They will be stable, meaning there will never be new ones that will make your application less robust? Even if you do, what did you gain from this?

So let’s look at a more likely situation in real application. Let’s look at the situation demonstrated in Lucas Polo’s response. There can occur several exceptions. Trying to treat all as if it were the same thing falls into the same problem.

Let us imagine an even more complicated problem. You call a method, you don’t know what it does (even if you know it doesn’t help much) and it can be modified without you knowing it. It can have many more exceptions. There may be exceptions caused by programming errors that you are capturing and saying that there is only one Número inválido when the problem is much more serious. There may be errors of Runtime (for real) like resource accesses (files, networks, Dbs) that fail and are definitely not invalid numbers.

If you are lucky (or unlucky) you will use an API that uses checked Exception and know what must treat (by explicitly capturing or delegating). Then you capture the Exception and "handles" what the API requires. " Treats" all exceptions that are mandatory giving a unique solution that most likely does not solve the real problem.

Even in your simple example it may not seem so complicated to treat all exceptions individually, but then in the future you need to put new operations within the try and forgets to take care of all possible new exceptions. Virtually anything you do in a program can trigger an exception.

Exception is an extremely complicated flow control. Much more complicated than the goto that everyone has already understood that it is complicated. She comes from where you can’t imagine (Joel Spolsky’s article about this).

Ground rule

Just treat an exception that you knows specifically what to do with it. If you want to treat a NumberFormatException, give treatment to the NumberFormatException. If you’re gonna treat one FileNotFoundException, take care of it and do not do other things. If you can treat all the exceptions that are IOException in the same way, ok, this is the most specific and it can be treated. And of course you can deal with the Exception when it is as specific as possible. This usually only occurs in "high" application methods, the Main(), for example. In general the only thing to do in this case is to warn the user and register the error (log) for a professional to review.

If you do not know what to do with each of the exceptions you are capturing, do not capture. Capture will only mask what is happening. If you cannot solve the problem let it propagate to a higher level. This is especially true for exceptions caused by programming errors. These errors need to be fixed by the programmer, there is nothing else to do. Capturing exceptions unintentionally hide programming errors.

Why do you wear Exception?

The impression I have is that it gives a false sense of security to capture all possible problems. But in programming every time you try to solve something you don’t know why, or "just in case," you end up making a mistake. Some just leave the code dirtier, others cause real problems.

To conclude, the final example of Lucas Polo is good until he decides to capture the Exception right there (note that Oracle does not recommend this). All right, it’s just a fictional example posted here but if it’s used in production you’ll be handling the exception "just in case". It is probably decentralizing and duplicating the same treatment at various points of application. Look in your code to see if there are no duplicates in the treatment.

Of course you may have to do something specific right there for all the exceptions, but this is extremely rare. Usually the treatment of Exception is only useful in the Main() or other entry point, in the method that controls an entire framework (UI, for example), or in a thread.

  • Don’t swallow exceptions, mostly unintentionally.
  • Do not mix unrelated exceptions.
  • Do not treat what cannot be treated, even without wanting.
  • Use the thought "every time I capture one Exception I don’t know what’s happening to my program".

This last one is even valid when using this catch on Main(). But that’s okay, in this case it’s normal that you don’t know. When catching an exception there is critical to have recorded all the details of the exception, so you may find that you could have captured a more specific exception elsewhere and handled it better. But then you have concrete information that capture is necessary.

  • 1

    Like Sidenote. Unfortunately Java ended up falling in love with the "one mechanism solves everything" and exceptions are used extensively to treat normal application flow. But this is another problem I deal with in other posts on the subject. Follow the link I provided above.

  • 1

    Essentially I program to run on android. And in the UI Thread the entire untreated exception will make the app crash. So I often go general, because I don’t know what else can come out of a method, even if it makes debugging the error :/

  • 1

    I don’t know specifically the framework and UI you’re using and it even makes sense to have one capture of Exception in thread UI to make the final capture before the application breaks. In general in capture serves to catch the programming errors, including the forgetfulness errors of having captured something that deserves to be captured elsewhere, which is still a programming errors. By luck (or bad luck, it is debatable) in Java the important exceptions you will be required to treat next to the same error (but must treat in a specific way). The more you swallow exceptions unintentionally..

  • 2

    ... the more you will have difficulty understanding with exceptions, the more your application will become unpredictable. If you do not know what to capture and what to do to resolve The fail, do not capture! I know it’s a lot to read but the links contained in my answer pointed out at the beginning of this are fundamental for you to better understand the functioning and the problems of capturing exceptions the wrong way. When you start using exceptions in the right way your life will get much better. Ask specific questions if you still need to understand more things but stop suffering :)

  • 1

    This answer is not only useful but also moves and makes people abandon bad habits. If you could give +2.

27

If only one Exception is triggered in your code snippet, it won’t make much difference, but if more than one can be released in the same snippet, you won’t be able to give a specific treatment. The best approach is to leave a treatment for each type and if you want to group, from Java 7 you can do this way:

public class ExampleExceptionHandlingNew
{
   public static void main( String[] args )
   {
    try {
        URL url = new URL("http://www.yoursimpledate.server/");
        BufferedReader reader = new BufferedReader(
            new InputStreamReader(url.openStream()));
        String line = reader.readLine();
        SimpleDateFormat format = new SimpleDateFormat("MM/DD/YY");
        Date date = format.parse(line);
    }
    catch(ParseException | IOException exception) {
        // handle our problems here.
    }
   }
}

This makes it easier to group, and if necessary, you can take a more specific approach to each exception and at the end, if any pass through, you can capture Exception for unexpected cases:

public class ExampleExceptionHandlingNew
{
   public static void main( String[] args )
   {
    try {
        URL url = new URL("http://www.yoursimpledate.server/");
        BufferedReader reader = new BufferedReader(
            new InputStreamReader(url.openStream()));
        String line = reader.readLine();
        SimpleDateFormat format = new SimpleDateFormat("MM/DD/YY");
        Date date = format.parse(line);
    } catch(ParseException exception) {
        // handle our problems here.
    } catch(IOException exception) {
        // your code
    } catch(Exception exception) {
        // 
    }
   }
}

There’s more here on this link from Oracle, where I also took the example.

  • 1

    I liked the second part, because the guy deals with the known exceptions and if he falls for the last one at least he already knows that it was none of the previous two. (+1)

2

Specifying or generalizing the exception treatment will depend a lot on what the application needs. Imagine a very large system and that the error will be displayed on the user screen. How will you know which point to attack if you don’t know where the error comes from? Is it application error or data mass error? Will the user report the error to the development team or correct its data entry? What will be presented on the screen will give you the direction of what to do. Use common sense. Remember that one part of development is creating the application and the other is maintaining.

-1

The idea would be you know exactly what error the application is generating to treat it properly.

When an application generates more than one error in the same part it becomes clearer why it is important to use to Try, catch it this way.

Another thing they didn’t comment on was Finally which is a chunk of code that will always run independent of the exception, and even if there is no exception this code will run. Would look like this:

try{

}catch(Exception e){

}finally{

}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.