Throwable Class
Basic Exception Handling
Better Exception Handling
Finally Keyword
Assertions
Logging
Programs can fail for various reasons:
Some of these issues are coding errors, while others are beyond the coder's control. However, anticipating such errors and handling them appropriately is crucial.
The Error
hierarchy describes internal errors and resource exhaustion situations.
Error
.IOError
, StackOverflowError
, and OutOfMemoryError
are a few of the commonly encountered Errors
IOError
- serious I/O error has occurredStackOverflowError
- application recurses too deeply.OutOfMemoryError
- JVM cannot allocate an object because it is out of memoryError
or RuntimeException
class.RuntimeException
is considered to be the programmer's fault.ArrayIndexOutOfBoundException
can be avoided by testing array index against array boundsNullPointerException
can be avoided by testing for null values.IOException
is potentially not the programmer's fault.FileNotFoundException
can be thrown when trying to read from a remote file that a person incidentally removes.SQLException
can be thrown as a result of a faulty network connection.Here are a couple of ways an exception can be thrown:
With a coding mistake:
String[] myEmptyArray = new String[0];
System.out.println(myEmptyArray[0]);
(throws an ArrayIndexOutOfBoundsException, since there is no index 0 in this array)
By throwing one explicitly, using the throw keyword:
throw new Exception();
throw new Exception("Oops! Something broke.");
throw new RuntimeException();
throw new RuntimeException("Oops! I broke something.");
import java.io.*;
class FilePrinter {
private final BufferedReader reader;
public FilePrinter(String fileDirectory) {
// What if the file does not exist?
this.reader = new BufferedReader(new FileReader(fileDirectory));
}
public void printFile() {
String line = null;
do {
// What if the System fails to read in the next line?
// (For example if the file was suddenly closed, modified, or deleted)
line = reader.readLine();
System.out.println(line);
} while (line != null);
}
}
import java.io.*;
class FilePrinter {
private final BufferedReader reader;
public FilePrinter(String fileDirectory) throws FileNotFoundException {
this.reader = new BufferedReader(new FileReader(fileDirectory));
}
public void printFile() throws IOException {
String line = null;
do {
line = reader.readLine();
System.out.println(line);
} while (line != null);
}
}
import java.io.*;
class FilePrinter {
private final BufferedReader reader;
public FilePrinter(String fileDirectory) throws FileNotFoundException {
this.reader = new BufferedReader(new FileReader(fileDirectory));
}
public void printFile() throws IOException {
String line = null;
do {
line = reader.readLine();
System.out.println(line);
} while (line != null);
}
public void tryPrintFile() {
try {
printFile();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
FilePrinter
class, theFileNotFoundException
printFile()
throws an IOException
FilePrinter
object, then print its contents?public class FilePrinterTest {
private static final String invalidFileName = "";
@Test(expected = FileNotFoundException.class)
public void testInstantiation() throws FileNotFoundException {
FilePrinter fpt = new FilePrinter(invalidFileName);
}
// Attempt to instantiate FilePrinter with invalid name
// Attempt to invoke method on unininstatiated FilePrinter object
@Test(expected = NullPointerException.class)
public void testNullPointer() throws NullPointerException {
FilePrinter fpt = null;
try {
fpt = new FilePrinter(invalidFileName);
} catch (FileNotFoundException e) {
System.out.println("Printing stack trace...");
e.printStackTrace();
}
fpt.tryPrintFile();
}
@Test(expected = NullPointerException.class)
public void testMultiThrowSignature() throws NullPointerException, FileNotFoundException {
testNullPointer();
testInstantiation();
}
}
public class FilePrinterTest {
private static final String invalidFileName = "";
public void testInstantiateAndPrint() {
FilePrinter fpt = null;
try {
fpt = new FilePrinter(invalidFileName);
} catch(FileNotFoundException fnfe) {
fnfe.printStackTrace();
}
try {
fpt.printFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class FilePrinterTest {
private static final String invalidFileName = "";
public void testInstantiateAndPrint() {
FilePrinter fpt = null;
try {
fpt = new FilePrinter(invalidFileName);
fpt.printFile();
} catch(FileNotFoundException fnfe) {
// handle FileNotFoundException
fnfe.printStackTrace();
} catch(IOEXception ioe) {
// handle IOException
ioe.printStackTrace();
}
}
}
public class FilePrinterTest {
private static final String invalidFileName = "";
public void testInstantiateAndPrint() {
FilePrinter fpt = null;
try {
fpt = new FilePrinter(invalidFileName);
fpt.printFile();
// bit-wise operator supported by java 1.7+
} catch(FileNotFoundException | IOException exception) {
// handle all exceptions the same way
exception.printStackTrace();
}
}
}
public class FilePrinterTest {
private static final String invalidFileName = "";
public void testInstantiateAndPrint() {
FilePrinter fpt = null;
try {
fpt = new FilePrinter(invalidFileName);
fpt.printFile();
} catch(Exception exception) {
// handle all exceptions the same way
exception.printStackTrace();
} catch(IllegalArgumentException iae) {
iae.printStackTrace();
}
}
public void parseIntegerInput(String s) {
try {
Long.parseLong(s);
} catch(NumberFormatException e) {
e.printStackTrace();
throw new IllegalArgumentException();
}
}
}
n
levels deep, where n
is the recursive depth of the method call.StackTraces
finally
block is executedfinally
clause from try/catch
clausesfinally
block is executedtry
block is thrown.catch
clause.finally
clause, if the catch
clause does not throw an exception.finally
clause from try/catch
clausesclass BookExample {
public void example1() {
InputStream in = ... ;
try {
try {
// code that may throw exception
} finally {
in.close();
}
} catch(IOException ioe) {
/// handle exception some way
}
}
}
When a method overrides a method from a superclass or interface, it is not allowed to add checked exceptions. It is, however, allowed to declare fewer exceptions or declare a subclass of a declared exception. Methods declare exceptions with the keyword throws.
Adding a checked exception to a method won't compile:
class HasNoMovesException extends Exception { }
class Dancer {
public void dance() { }
}
class Boogie extends Dancer {
public void dance() throws HasNoMovesException {
// DOES NOT COMPILE
}
}
...declaring fewer exceptions, or declaring a subclass of the exception type are perfectly legal, however.
class Dancer {
public void hop() throws HasNoMovesException { }
}
class Boogie extends Dancer {
public void dance() { }
}
class Dancer {
public void dance() throws Exception { }
}
class Boogie extends Dancer {
public void dance() throws HasNoMovesException { }
}
You could also throw it explicitly:
public void dance() {
throw new RuntimeException("I have no moves!");
}
assert
, which takes two forms:assert condition;
assert condition : expression;
assert
evaluates a condition, then throws an AssertionError
if it is false. The second argument expression is a message String.false
, no exception is thrown.-ea
option.java -ea MyProject
enables for entire projectjava -ea:MyClass -ea:com.zipcodewilmington.MyProject
enables for MyClass
System.out.println
to check against troublesome code.INFO
or higher to console.SEVERE
WARNING
INFO
CONFIG
FINE
FINER
FINEST
public class LogDemo {
// it is advised that you name your logger the same as your Main Application package
Logger logger = Logger.getLogger("com.zipcodewilmington.MainApplication");
public void logTest() {
logger.setLevel(Level.SEVERE); // log severe
logger.setLevel(Level.WARNING); // log severe, warning
logger.setLevel(Level.INFO); // log severe, warning, info
logger.setLevel(Level.CONFIG); // log severe, warning, info, config
logger.setLevel(Level.FINE); // log severe, warning, info, config, fine
logger.setLevel(Level.FINER); // log severe, warning, info, config, fine, finer
logger.setLevel(Level.FINEST); // log severe, warning, info, config, fine, finer, finest
}
}