简体   繁体   中英

Java API and checked/unchecked exceptions confusion

The question about checked and unchecked exceptions was raised here and on other websites million times, but I'm still confused with so different answers.

In many answers and articles we can read general statements like:

Unchecked runtime exceptions represent conditions that, generally speaking, reflect errors in your program's logic and cannot be reasonably recovered from at run time.

and for checked exceptions

represent invalid conditions in areas outside the immediate control of the program (invalid user input, database problems, network outages, absent files)

both quotes are from http://www.javapractices.com/topic/TopicAction.do?Id=129 and are cited many times.

We can read similar statements on oracle website:

Runtime exceptions represent problems that are the result of a programming problem, and as such, the API client code cannot reasonably be expected to recover from them or to handle them in any way http://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html

Lets take simple example with reading Number with Scanner:

Scanner sc = new Scanner(System.in);
int userInput = sc.nextInt();
System.out.println(userInput);

nextInt() throws InputMismatchException when I type ie "asdf" instead of int. InputMismatchException is RuntimeException but according to statements above this is the first example of checked exceptions "invalid user input".

When I look at checked exceptions I am even more confused. For example NPE vs FileNotFoundException - both can be prevented by simple if-else, so why first one is unchecked and second is checked?

Oracle website has bottom line guideline:

If a client can reasonably be expected to recover from an exception, make it a checked exception. If a client cannot do anything to recover from the exception, make it an unchecked exception.

So according to that I can recover from FileNotFoundException or IOException but I can't from NPE or ArrayIndexOutOfBoundsException? This makes no sense.

Maybe someone has better explanation to this with some better example?

To be very simple and factual :

  • an unchecked exception ( Runtime class and children) conveys an unexpected exception. In general, the caller should not know how to handle it and doesn't wait for it in any of his scenarios.

  • a checked exception conveys a exception that you may consider as a "normal" exception and the caller know how to handle it. It is probably not the nominal case for him but the caller knows that it could happen and should prepare himself to handle it.

In your example :

nextInt() throws InputMismatchException when I type ie "asdf" instead of int. InputMismatchException is RuntimeException but according to statements above this is the first example of checked exceptions "invalid user input".

When a method calls nextInt() the caller waits for a int value. It is the excepted scenario. If it was not the case the user would do rather : next() to retrieve a String object and try then to convert it by something that suits.
When you invoke nextInt() , the caller waits for an int as he has requested it. Force him to handle InputMismatchException as a checked Exception would be counter-intuitive.


So according to that I can recover from FileNotFoundException or IOException but I can't from NPE or ArrayIndexOutOfBoundsException? This makes no sense.

I think JDK Exceptions as FileNotFoundException or IOException are special cases. They are probably checked not necessarily because the client of these classes waits for that the file is not found or the stream generates some exceptions during reading or writing but rather because a stream may be in a not suitable state and consequently raises exception for many external reasons (file locked, lack of right, file moved to another place or to a not reachable network and so for...). A file that generates an exception is probably considered as something that is important to handle. So, the JDK specification prefers that the caller handles it explicitly.

Besides, before the arrival of the try-with-resources statement, the caller should explicitly close streams in case of exceptions.


NPE and ArrayIndexOutOfBoundsException are generally programming errors. The application cannot do a processing to recover specifically errors which it doesn't know the existence. So why make them checked ?

every single exception may or may not be recoverable in your app. it always depends on the context. if some object is null and you get NPE (unchecked) it may result in an empty expression language expression (so in this particular context, this situation is perfectly recoverable). on the other hand, you may get IOException (checked) which is irrecoverable because your web application can't connect to database and therefore is useless in context of this particular web application.

Maybe someone has better explanation to this

there is a better explanation: making checked and unchecked exception was simply a wrong design decision of language authors. and it decision won't be changed as long as java remains backward compatible.

so just:

  1. ignore this artificial division (as other modern languages decided to do)
  2. when design your api always use unchecked
  3. when working with checked exception, wrap them in unchecked deep down the call stack (your life will be easier)
  4. when calling a method always think/check what exceptions it may throw (checked or unchecked) and decide for every one of them if you should handle it or rethrow/pass through

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM