Exceptions
Exceptions are things that worth special consideration. This could mean that the execution of some method is "exceptional" because it might result in errors.
We, therefore, handle exceptions in our program to avoid errors.
There are two main branches of exceptions, checked and unchecked exceptions.
Summary
Exception | Checked | Unchecked |
---|---|---|
Error | Compile-time | Run-time |
Occurrence | Anticipate and handle | Unanticipated |
Example | IOException FileNotFoundException ... | NullPointerException ArithmeticException ... |
Strategy | Must declare or catch | Result in bugs to be fixed |
Try-catch
One way to deal with known exceptions is to put dangerous code in a try-catch block.
try {
// Might result in FileNotFoundException
FileReader file = new FileReader(args[0]);
// any other code that might result in exceptions
} catch (FileNotFoundException e) {
// do something about the exception
}
When we catch an exception, we could resolve it by printing out some message to the caller, or we could simply throw the exception at the caller. Actively raising an exception is still considered a way of "handling" exceptions.
try {
// something dangerous here
} catch (IOException e) {
// simply throw exceptions
// can throw different exceptions
throw new NullPointerException("My exception message here");
}
Throw
The keyword throw is used to raise exceptions. It could be used within a catch block to resolve another exception. It could also be used whenever we would like to raise an exception.
// some method
public void test() {
throw new ArrayStoreException("Throwing it because I want to");
}
Throws
Instead of using try-catch, we could simply declare in the method signature that this method could throw some exceptions that callers must look out for. Note that we don't declare unchecked/run-time exceptions because they cannot be anticipated.
Let's see some code examples.
// might throw unchecked exceptions, which is typical
void willThrowUnchecked() {
// does some stuff
throw new NullPointerException("this is an unchecked exception");
}
// DON'T DO THIS, unchecked exceptions need not be declared
void willThrowUnchecked2() throws NullPointerException {
throw new NullPointerException("this is an unchecked exception");
}
// might throw a checked exception
void willThrowChecked() throws IOException {
// pretend that it might throw an exception
throw new IOException();
}
// DON'T DO THIS, checked exceptions must be declared
// will not compile
void willThrowChecked2() {
throw new IOException();
}
Unchecked exceptions
- The function call within this method body does not throw checked exceptions, hence ok to not do any handling.
// will compile
void useUnchecked() {
willThrowUnchecked();
}
- Unchecked exceptions need NOT be anticipated. No known checked exceptions anticipated. Hence ok to not do any handling.
// will compile
void useUnchecked2() {
willThrowUnchecked2();
}
- We can handle unchecked exceptions, if we want to
// will compile
void useUnchecked3() {
try {
willThrowUnchecked();
} catch (NullPointerException e) {
System.out.println("hello");
}
}
Checked exceptions
- If we don't handle checked exceptions, we are not allowed to use potentially dangerous methods.
// will not compile
void useChecked() {
willThrowChecked();
}
- We declare that the current method is dangerous, so whenever this method is called, the caller needs to handle it. we passed the responsibility to the caller of this method. This is considered "handling" exceptions as well.
// will compile
void useChecked2() throws IOException {
willThrowChecked();
}
- We handled the exception using try-catch, safe and sound.
// will compile
void useChecked3() {
try {
willThrowChecked();
} catch (IOException e) {
System.out.println("I handled it!");
}
- We handled it by throwing another exception, still safe.
// will compile
void useChecked4() {
try {
willThrowChecked();
} catch (IOException e) {
throw new NullPointerException("Hey there is a problem!");
}
}
- If we throw a checked exception as a response, we must declare it.
// will NOT compile
void useChecked4() {
try {
willThrowChecked();
} catch (IOException e) {
throw new IOException ("Hey there is a problem!");
}
}
// will compile
void useChecked4() throws IOException {
try {
willThrowChecked();
} catch (IOException e) {
throw new IOException ("Hey there is a problem!");
}
}
Throws vs Throw
The two keywords are not exactly comparable because they serve different purposes. They can co-exist in a single method. Hence, the usage of the two reserved words depend on the situation.
Summary
Throws | Throw | |
---|---|---|
Purpose | To declare checked exceptions | To throw any exceptions |
Usage | when the method body contains code that might throw checked exceptions | As a way to raise exceptions (both checked and unchecked) to the caller |
Example | void test() throws IOException {} |
throw new NullPointerException("WRONG"); |
Top comments (0)