Java - where and how should exceptions be used?

前端 未结 9 1426
天涯浪人
天涯浪人 2021-01-02 05:03

I was reading some things about exception handling in Java, to be able to write better code. OK, I admit, I am guilty; I\'ve used too much try-catch{} blocks, I\'ve used

相关标签:
9条回答
  • 2021-01-02 05:11
    1. While I don't have any numbers, I don't believe that try-catch has any significant impact on performance (not that I have seen). I think that if you don't run into many exceptions, the performance impact will be basically nothing. But in any case, it's best to care about implementing code correctly first and achieving good performance second -- a lot easier to do the second once the first is done.

    2. I think the exception class should be specific as to what the exception really is. The problem I have with Java's SQLExceptions is that they give you no information about what really went wrong. Spring uses far a set of more descriptive database exceptions (deadlock exceptions, data integrity exceptions, etc.) That way you can tell what the problem really was.

    3. Checked exceptions can be annoying, but I don't think they're always bad. For example, Spring uses unchecked exceptions for database errors, but I still check for them and either 1) handle them right there, if possible, or 2) wrap in a more general exception that the shows that the component failed.

    4. Unfortunately, I can't think of any good specific exceptions. However, like I said, I've found Spring's exception rules to be helpful and yet not annoying, so maybe you could look at some Spring docs. The Spring database classes are a good example.

    0 讨论(0)
  • 2021-01-02 05:11
    • Using excessive try-catch() has a negative impact on performance?

    This sounds like micro optimization and, if this really has a performance impact, you'll have to deal with a lot of bigger performance problems before to face this one.

    • Using specific exception types is better? What if i missed to catch one of the possible X types of exceptions that could occur? Frankly, I've heard and use a mere 10% i think of the Java standard exceptions, in 2-3 years. Yes, someone said that if the caller don't know how to deal with the trowed exceptions, he SHOULD NOT HAVE THE RIGHT to call the throwing method. Is that right?

    I'm not sure I understood the question but I'd say: "If you don't know what to do with an exception, re-throw it".

    • I've read this article of Anders Hejlsberg, saying that checked exceptions are bad. Should that indicate that convenient exception swallowing is advised in some cases?

    Hell no. This just means that unchecked exception should be preferred in some cases especially when the user won't know what to do with a checked exception (e.g. SQL exception), or if there is not possible recovery,...

    • A picture is worth 1000 words..i guess some examples will help a lot here.

    Spring's DataAccessException is a very good example. Check chapter 10. DAO support.

    0 讨论(0)
  • 2021-01-02 05:11

    Return value vs. throwing an exception

    The fundamental difference between an exception and a return value is that the return value is delivered to your immediate caller, whereas an exception is delivered to a catch clause anywhere in the call stack. This allows to reuse the same exception handler for many different kinds of exceptions. I recommend that you favor exceptions over return codes if and only if you need that feature.

    Performance impact.

    Every instruction has a negative effect on performance, including those in catch-blocks. However, any modern CPU can throw and handle millions of exceptions per second, so unless you throw thousands of them you won't notice a thing.

    Specific exceptions

    For throwing, be specific to allow specific handling. For handling, you can be generic, but you should be aware that arbitrary exceptions can be delivered to your handler, including unchecked ones not declared by your callees.

    checked

    The debate rages whether methods should use checked or unchecked exceptions. Never just swallow an exception. Handle or rethrow it. It simplifies maintenance if you don't discard evidence about failures.

    Example

    An application I worked on recently receives commands over the network which it then executes. This usually involves further interaction with remote systems, which might fail for a host of reasons. The methods to carry out the command don't catch any exceptions, letting them bubble of the call stack to the central exception handler in the command listener, which does the following:

    for (int retries = 0;; retries++) {
        try {
            commandService.execute(command);
            return;
        } catch (Exception e}
            Log.error(e);
            if (retries < 3) {
                continue;
            } else {
                saveForAnalysis(command, e);
                alertOperator();
                return;
            }
        }
    }
    

    We intentionally did not catch & rethrow exceptions in the processing logic, as we felt this would have added no value.

    0 讨论(0)
  • 2021-01-02 05:14

    One thing that we have done on our team is to have custom exceptions for our errors. We are using the Hibernate Validator framework, but you can do this with any framework, or stock exceptions.

    For example, we have a ValidationException to handle validation errors. We have a ApplicationException to handle system errors.

    You DO want to minimize your try-catch-ing. In our case, we will have the validator collect ALL the validations in "InvalidValue" objects, and then throw a single ValidationException with the invalid value information bundled into it. Then you can report to the user which fields were in error, etc.

    In the case you mentioned of a database error - you may not want to send the stacktrace to the UI (logging it is a good idea). This is a case where you can catch the database exception, then throw your own ApplicationException to your GUI. Your GUI won't have to know how to deal with an infinite number of server errors, but can be set to deal with the more generalized ApplicationException - possibly reporting that there is a problem with the server, and indicating that the user should contact your customer support department to report the problem.

    Lastly, sometimes you can't help but use a lot of try/catch blocks because of the external APIs you rely on. This is fine. As mentioned before, catch the external exception, and format it into one which makes more sense to YOUR application. Then throw the custom exception.

    0 讨论(0)
  • 2021-01-02 05:15

    The general rule of thumb for exception is, if you can do something about it, catch it and handle it, if you can't, re-throw it to the next method. To get into some of your specifics:

    1. No, using excessive try/catch will not have a performance impact
    2. Using the most specific type of exception you can. For example, you shouldn't generally throw Exception if you can avoid it. By throwing a specific type, you are letting the user know what can go wrong. However, you can rethrow it as something more generic so callers that are not concerned with the specific exception don't need to know about it (for example, a GUI won't care if it's an IOException vs an ArrayIndexOutOFBoundsException).
    3. You will find people that like checked exceptions more and you will find people that like unchecked more. In general, I try to use unchecked exceptions because there is generally not a lot you can do about most checked exceptions, and you can still handle unchecked exceptions, you just don't have to. I frequently find myself rethrowing checked exceptions since I can't do much about them (another strategy is to catch a checked exception and rethrow it as an unchecked so classes higher in the chain don't need to catch it if they don't want).

    I generally like to log exceptions at the point of where they are caught - even if I can't do anything about it, it helps to diagnose the problem. If you are not familiar with it, also look into the method Thread.setDefaultUncaughtExceptionHandler. This allows you to handle exceptions that are not caught by anyone and do something with it. This is particularly useful with a GUI app since the exception might otherwise not be seen.

    To get into some examples:

    try {
       // some database operation
    }
    catch (IOException ex) {
       // retry the database operation. then if an IO exception occurs rethrow it. this shows an example doing something other than just catch, logging and/or rethrowing.       
    }
    

    I'll be happy to expand on any parts of this if you'd like.

    0 讨论(0)
  • 2021-01-02 05:17

    se-radio made a podcast episode about that topic of error handling that explains some philosophy about how to use exceptions, which can be restated as "Where to absorb them".

    The main thing I retained is that most functions should let them bubble up, and most exceptions details should end up in a log file. Then the functions pass only global messages saying that something happened.

    In a sense, this leads to a sort of exception hierarchy : one for each layer of code.

    As I think they said, it doesn't make sense to explain to the user that such DB cluster failed because the DNS was unavailable, or because the disk was full. At that level, something happend that couldn't allow the transaction to complete, that's all the user has to know.

    Of course, the developpers/administrators will be happy to see more details, that's why at the DB layer, the specific exceptions should be logged.

    0 讨论(0)
提交回复
热议问题