This is the difference between checked exceptions and unchecked exceptions.
A checked exception is part of a method signature, and is required to either be caught or declared to be thrown when the method is used. They are subclasses of Exception
themselves.
Some examples include a particular constructor of Scanner
, or more formally, Scanner#<init>(File file)
.
Checked exceptions are declared to be thrown typically because it is possible to recover from the exception. For instance, if you were to create a Scanner
that read lines from a file, and the file didn't exist, what could you reasonably do besides ask them to re-specify the location?
An example:
Scanner sc = new Scanner(System.in);
boolean found = false;
String path = sc.nextLine();
while(!found) {
try {
sc = new Scanner(new File(path));
found = true;
} catch (FileNotFoundException e) {
System.out.println(path + " was not valid. Please try again.");
path = sc.nextLine();
}
}
An unchecked exception is not part of a method signature, and may be thrown for any particular reason. They are subclasses of RuntimeException
.
One of the most common you'll encounter would be NullPointerException
. This particular exception could occur in the most innocuous of ways, such as:
Integer i = null;
System.out.println(i + 2); // NPE on unboxing
It is not typically expected for one to be able to recover from the exception; in layman's terms, something has gone wrong with the assumptions made about the flow of code. That is to say, writing this is almost certainly a code smell:
Integer i = null;
try {
System.out.println(i + 2);
} catch(NullPointerException e) {
System.out.println("i was null!?");
}
Most modern frameworks will allow you to specify a specific state that your application enters when such an error occurs - if it's a web driven application, you can have those sorts of runtime exceptions handled as a 500.
There is also Error
, which is a special case of unchecked exceptions - you should definitely not recover from this, since it's indicated that something has gone terribly, terribly wrong with the JVM.
For instance, this is something you don't want to see:
public void recurse() {
try {
recurse();
} catch (StackOverflowError e) {
System.out.println("We went in too deep.");
}
}