Exceptions are the vital important mechanism in java programming.
Handling errors in your programs has direct impact on whether
your application run or not. It direct affects on all aspects of
developing software. Exceptions allow to separate error-handling
code from regular code, it is make your code more clear and easy
to maintain.
Checked and Unchecked Exceptions
There are two kinds of exceptions in Java: checked and unchecked exceptions.
All checked exceptions are verified by compiler. You must handle
exception of this type in method or you must declare that your method
throws exception. There are two super-class of unchecked exceptions:
RuntimeException and Error. Diagram below depicts
exception classes hierarchy.
Handling Exceptions
You can handle exception otherwise you must declare it. Also you can handle some exceptions
and declare others.
| Handle Exceptions | Declare Exceptions |
public void myMethod() {
try {
. . .
}
catch (ExceptionType1 e) {
. . .
}
catch (ExceptionType2 e) {
. . .
}
finally {
. . .
}
|
public void myMethod() throws ExceptionType1,ExceptionType2 {
. . .
}
|
Example:
Comments:
Lines with invalid data in source file are ignored, we just register it.
Declaration of IllegalArgumentException can be omitted, because it belongs to
RuntmeException.
FileNotFoundException, IOException are propagated to the caller,
because it can make more appropriated decision for these cases.
Creating your own exception classes
Before creating your own exception you must double check existing
exceptions in Java API. If you can find what you need, use standard
exception.
If you have decided to create your own exception, keep following rules:
Choose a superclass from exception classes hierarchy
which most close to yours and extend it.
Avoid to extend Error and RuntimeException.
Good practice to append the word "Exception" to the end of your class.
Example:
Throwable class, getStackTrace, initCause, getCause
Class Throwable is the main super-class for all exceptions. It has:
Constructors
| Throwable() |
| Throwable(String message) |
| Throwable(String message, Throwable cause) |
| Throwable(Throwable cause) |
Methods
| Throwable | fillInStackTrace() |
| Throwable | getCause() |
| String | getLocalizedMessage() |
| String | getMessage() |
| StackTraceElement[] | getStackTrace() |
| Throwable | initCause(Throwable cause) |
| void | printStackTrace() |
| void | printStackTrace(PrintStream s) |
| void | printStackTrace(PrintWriter s) |
| void | setStackTrace(StackTraceElement[] stackTrace) |
| String | toString() |
getStackTrace
Provides programmatic access to the stack trace information printed by printStackTrace().
It returns array of StackTraceElement objects. Class StackTraceElement contains methods:
getClassName(), getFileName(), getLineNumber(), getMethodName() .
WARNINGS:
Some virtual machines may omit one or more stack frames from the stack trace.
File and line number information may not exist under JIT compilers and dynamic,
optimizing compilers (like Sun Microsystems'HotSpot).
initCause
Initializes the cause of this throwable to the specified value.
(The cause is the throwable that caused this throwable to get thrown.)
You can use specific constructor instead of using this method.
This method can be called at most once, as rule immediately after
creating the throwable.
getCause
Method retrieves cause of exception. A null value is permitted,
and indicates that the cause is nonexistent or unknown.
Best Practices in Exception Handling
In the catch block log exception or throw other exception, never do both.
Declare and catch the specific checked exceptions. Try to avoid following styles:
public void foo() throws Exception {
and
catch (Exception e) {
If your method can throw many exceptions, that basically
mean the same thing to the caller, wrap them in a single checked
exception:
public void foo() throws MyException1,MyException2,...,MyExceptionN {
if they have the same super class, change you code to:
public void foo() throws MySuperException {
else - you can create new exception MyGroupException and throw it with different causes:
public void foo() throws MyGroupException {
. . .
catch (MyException1 e) {
throw new MyGroupException(e);
}
. . .
catch (MyExceptionN e) {
throw new MyGroupException(e);
}
If you return null in catch block, you are losing the information forever.
Try to never return null (not only in catch block), throwing appropriated exceptions make
your code more robust and controlled.
Don't ignore InterruptedException. In many cases it inform you to stop it's doing.