From Effective Java (Joshua Bloch)
- Use exceptions exclusively for exceptional conditions (never use for normal control flow)
- Use checked exceptions for recoverable conditions and runtime exceptions for programming errors.
- Avoid unnecessary use of checked exceptions
Avoid marked exceptions.
http://www.mindview.net/Etc/Discussions/CheckedExceptions http://www.ibm.com/developerworks/java/library/j-jtp05254/index.html
- Checked exceptions are often considered erroneous. This is not a bad idea, but people really donβt understand how to use them.
- Java frameworks such as Spring, Hibernate ... they all basically throw unchecked exceptions.
- C # did not implement checked exceptions as intended. Scala.
- This is not because he did not check that you cannot catch him.
- This is not because he did not check that you cannot translate it (wrap).
- This is not because he did not verify that he was not part of the contract. In fact, you can declare a method to throw excluded exceptions.
- Checked exceptions increase communication between the client and the library.
It is very important to understand that any part of the code may throw an exception. The fact is that this is not because the method declares an IOException, that it cannot throw any other exception. It can throw any other runtime exception (general or custom). With checked exceptions, developers tend to think otherwise and believe that catching an IOException will handle all exceptional cases, but this is not true!
Compile-time function only
Only the compiler will tell you when you forgot to catch or throw the checked exception. There is no difference at runtime.
This means that by using type-erase tricks, you can throw a checked exception without even requiring it to be part of the method contract.
You can find examples of this trick called SneakyTrow here: fooobar.com/questions/284396 / ...
Lombok also provides the @SneakyThrow annotation for applying methods, so you don't need to declare checked exceptions in the method signature.
Use only checked exceptions when the client of your class may recover from the exception.
This is a recommendation from Sun.
Basically, trying to connect to the database will throw a checked exception, and the retry strategy code will catch these checked exceptions when attemps connects. When the number of retries is exceeded, the retry strategy will throw an exception that throws an exception, which means that it is not an exception for recovery, because the recovery strategy has already been tried. You can use Spring RetryTemplate for this, by the way.
Avoid Exception Codes
The type of exception should be sufficient to make flow control decisions. Exception parsing or flow control will produce useless code. Add more exception types as many exception codes you have.
Crash fast
Let all unrecoverable exceptions be thrown to the IHM level. If you use a framework that declares checked exceptions, and you don't have a recovery strategy for them, feel free to wrap them in unchecked exceptions.
If you cannot recover, you should not do catch and write. Or, even worse, you should not do "catch and return null". This will lead to inconsistent software, and you will probably have another exception raised later in your program, but you wonβt be able to understand why. A return value of null will later throw a NullPointerException.
IHM-level technology may have an exception handler / mapper. Web IHM layers have exception mapping mechanisms, so you can say that "this exception generates a 404 error."
Functional approach
For information: in functional languages ββit is often considered improper practice to use exceptions to control flow. Instead of throwing exceptions, we usually return "extended types", for example [Error, MyResultType].
The returned instance is either an error or successful, and an instance of MyResultType is returned.
Exceptions not thrown for flow control
Creating an exception has a cost (creating a stacktrace). It costs a lot more than a regular thread using if, else ... Do not use them to control the flow if you can avoid them.
Basically, you can always avoid them, but in Java it is sometimes more convenient to use them to control flows in some situations. In functional languages, Either the monad helps again.
Use statements
If something from your program is considered a true developer, use assertions to ensure that your assertion is true. Take a look at Guava premises: https://code.google.com/p/guava-libraries/wiki/PreconditionsExplained
Or you can use Java built-in statements or some kind of custom code. This helps to quickly fail.