When to choose checked and unchecked exceptions

前端 未结 18 2298
南方客
南方客 2020-11-22 04:13

In Java (or any other language with checked exceptions), when creating your own exception class, how do you decide whether it should be checked or unchecked?

My inst

相关标签:
18条回答
  • 2020-11-22 04:47

    I think we can think about exeptions from several questions:

    why does exeption happen? What can we do when it happens

    by mistake, a bug. such as a method of null object is called.

    String name = null;
    ... // some logics
    System.out.print(name.length()); // name is still null here
    

    This kind of exception should be fixed during test. Otherwise, it breaks the production, and you got a very high bug which needs to be fixed immediately. This kind of exceptions do not need be checked.

    by input from external, you cannot control or trust the output of external service.

    String name = ExternalService.getName(); // return null
    System.out.print(name.length());    // name is null here
    

    Here, you may need to check whether the name is null if you want to continue when it is null, otherwise, you can let it alone and it will stop here and give the caller the runtime exception. This kind of exceptions do not need be checked.

    by runtime exception from external, you cannot control or trust the external service.

    Here, you may need to catch all exceptions from ExternalService if you want to continue when it happens, otherwise, you can let it alone and it will stop here and give the caller the runtime exception.

    by checked exception from external, you cannot control or trust the external service.

    Here, you may need to catch all exceptions from ExternalService if you want to continue when it happens, otherwise, you can let it alone and it will stop here and give the caller the runtime exception.

    In this case, do we need to know what kind of exception happened in ExternalService? It depends:

    1. if you can handle some kinds of exceptions, you need to catch them and process. For others, bubble them.

    2. if you need log or response to user the specific execption, you can catch them. For others, bubble them.

    0 讨论(0)
  • 2020-11-22 04:48

    On any large enough system, with many layers, checked exception are useless as, anyway, you need an architectural level strategy to handle how the exception will be handled (use a fault barrier)

    With checked exceptions your error handling stategy is micro-managed and its unbearable on any large system.

    Most of the time you don't know if an error is "recoverable" because you don't know in what layer the caller of your API is located.

    Let's say that I create a StringToInt API that converts the string representation of an integer to an Int. Must I throw a checked exception if the API is called with the "foo" string ? Is it recoverable ? I don't know because in his layer the caller of my StringToInt API may already have validated the input, and if this exception is thrown it's either a bug or a data corruption and it isn't recoverable for this layer.

    In this case the caller of the API does not want to catch the exception. He only wants to let the exception "bubble up". If I chose a checked exception, this caller will have plenty of useless catch block only to artificially rethrow the exception.

    What is recoverable depends most of the time on the caller of the API, not on the writter of the API. An API should not use checked exceptions as only unchecked exceptions allows to choose to either catch or ignore an exception.

    0 讨论(0)
  • 2020-11-22 04:48

    Here is a very simple solution to your Checked/Unchecked dilemma.

    Rule 1: Think of a Unchecked Exception as a testable condition before code executes. for example…

    x.doSomething(); // the code throws a NullPointerException
    

    where x is null... …the code should possibly have the following…

    if (x==null)
    {
        //do something below to make sure when x.doSomething() is executed, it won’t throw a NullPointerException.
        x = new X();
    }
    x.doSomething();
    

    Rule 2: Think of a Checked Exception as an un-testable condition that may occur while the code executes.

    Socket s = new Socket(“google.com”, 80);
    InputStream in = s.getInputStream();
    OutputStream out = s.getOutputStream();
    

    …in the example above, the URL (google.com) may be unavailable to due the DNS server being down. Even at the instant the DNS server was working and resolved the ‘google.com’ name to an IP address, if the connection is made to google.com, at anytime afterword, the network could go down. You simply can not test the network all the time before reading and writing to streams.

    There are times where the code simply must execute before we can know if there is a problem. By forcing developers to write their code in such a way to force them to handle these situations via Checked Exception, I have to tip my hat to the creator of Java that invented this concept.

    In general, almost all the APIs in Java follow the 2 rules above. If you try to write to a file, the disk could fill up before completing the write. It is possible that other processes had caused the disk to become full. There is simply no way to test for this situation. For those who interact with hardware where at any time, using the hardware can fail, Checked Exceptions seem to be an elegant solution to this problem.

    There is a gray area to this. In the event that many tests are needed (a mind blowing if statement with lots of && and ||), the exception thrown will be a CheckedException simply because it’s too much of a pain to get right — you simply can’t say this problem is a programming error. If there are much less than 10 tests (e.g. ‘if (x == null)’), then the programmer error should be a UncheckedException.

    Things get interesting when dealing with language interpreters. According to the rules above, should a Syntax Error be considered a Checked or Unchecked Exception? I would argue that if the syntax of the language can be tested before it gets executed, it should be an UncheckedException. If the language can not be tested — similar to how assembly code runs on a personal computer, then the Syntax Error should be a Checked Exception.

    The 2 rules above will probably remove 90% of your concern over which to choose from. To summarize the rules, follow this pattern… 1) if the code to be execute can be tested before it’s executed for it to run correctly and if an Exception occurs — a.k.a. a programmer error, the Exception should be an UncheckedException (a subclass of RuntimeException). 2) if the code to be executed can not be tested before it’s executed for it to run correctly, the Exception should be a Checked Exception (a subclass of Exception).

    0 讨论(0)
  • 2020-11-22 04:49

    Checked Exception: If client can recover from an exception and would like to continue, use checked exception.

    Unchecked Exception: If a client can't do any thing after the exception, then raise unchecked exception.

    Example: If you are expected to do arithmetic operation in a method A() and based on the output from A(), you have to another operation. If the output is null from method A() which you are not expecting during the run time, then you are expected to throw Null pointer Exception which is Run time exception.

    Refer here

    0 讨论(0)
  • 2020-11-22 04:52

    Checked Exceptions are great, so long as you understand when they should be used. The Java core API fails to follow these rules for SQLException (and sometimes for IOException) which is why they are so terrible.

    Checked Exceptions should be used for predictable, but unpreventable errors that are reasonable to recover from.

    Unchecked Exceptions should be used for everything else.

    I'll break this down for you, because most people misunderstand what this means.

    1. Predictable but unpreventable: The caller did everything within their power to validate the input parameters, but some condition outside their control has caused the operation to fail. For example, you try reading a file but someone deletes it between the time you check if it exists and the time the read operation begins. By declaring a checked exception, you are telling the caller to anticipate this failure.
    2. Reasonable to recover from: There is no point telling callers to anticipate exceptions that they cannot recover from. If a user attempts to read from an non-existing file, the caller can prompt them for a new filename. On the other hand, if the method fails due to a programming bug (invalid method arguments or buggy method implementation) there is nothing the application can do to fix the problem in mid-execution. The best it can do is log the problem and wait for the developer to fix it at a later time.

    Unless the exception you are throwing meets all of the above conditions it should use an Unchecked Exception.

    Reevaluate at every level: Sometimes the method catching the checked exception isn't the right place to handle the error. In that case, consider what is reasonable for your own callers. If the exception is predictable, unpreventable and reasonable for them to recover from then you should throw a checked exception yourself. If not, you should wrap the exception in an unchecked exception. If you follow this rule you will find yourself converting checked exceptions to unchecked exceptions and vice versa depending on what layer you are in.

    For both checked and unchecked exceptions, use the right abstraction level. For example, a code repository with two different implementations (database and filesystem) should avoid exposing implementation-specific details by throwing SQLException or IOException. Instead, it should wrap the exception in an abstraction that spans all implementations (e.g. RepositoryException).

    0 讨论(0)
  • 2020-11-22 04:54

    We have to distinguish these two types of exception based on whether it is programmer error or not.

    • If an error is a programmer error, it must be an Unchecked Exception. For example: SQLException/IOException/NullPointerException. These exceptions are programming errors. They should be handled by programmer. While in JDBC API, SQLException is Checked Exception, In Spring JDBCTemplate it is an Unchecked Exception.Programmer doesn't worry about SqlException, when use Spring.
    • If an error is not a programmer error and the reason is coming from external, it must be a Checked Exception. For example: if the file is deleted or file permission is changed by someone else, It should be recovered.

    FileNotFoundException is good example to understand subtle differences. FileNotFoundException is thrown in case file is not found. There are two reason for this exception. If the file path is defined by developer or taking from end user via GUI it should be an Unchecked Exception. If the file is deleted by someone else, it should be a Checked Exception.

    Checked Exception can be handled in two ways. These are using try-catch or propagate the exception. In case of propagation of exception, all methods in call stack will be tightly coupled because of exception handling. That's why, we have to use Checked Exception carefully.

    In case you develop an layered enterprise system, you have to choose mostly unchecked exception to throw, but don't forget to use checked exception for the case you cannot do anything.

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