Exceptions, Assertions, Logging

What we’ll cover

Throwable Class

Throwable Hierarchy

Errors

Unchecked Exceptions

Checked Exceptions

Basic Exception Handling

What is Exception Handling?

Unchecked Unhandled Exception Example; Compile Error

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);
    }
}

Exception Handling; Signature Throw Clause

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);
    }
}

Exception Handling; Try / Catch

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) {
            throw new RuntimeException(ioe);
        }
    }
}

Better Exception Handling

Multi-Exception Handling

Multi-Exception Handling Examples

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) {
            throw new RuntimeException(e);
        }
        fpt.tryPrintFile();
    }

    @Test(expected = NullPointerException.class)
    public void testMultiThrowSignature() throws NullPointerException, FileNotFoundException {
        testNullPointer();
        testInstantiation();
    }

}

Dynamic Exception Handling; Expanded

public class FilePrinterTest {
	private static final String invalidFileName = "";
	public void testInstantiateAndPrint() {
	    FilePrinter fpt = null;
	    try {
	        fpt = new FilePrinter(invalidFileName);
	    } catch(FileNotFoundException fnfe) {
            throw new RuntimeException(fnfe);
	    }

	    try {
	        fpt.printFile();
	    } catch (IOException e) {
	        throw new RuntimeException(e);
	    }
	}
}

Dynamic Exception Handling; Compressed

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
	        throw new RuntimeException(fnfe);
	    } catch(IOEXception ioe) {
	        // handle IOException	    
	        throw new RuntimeException(ioe);
	    }
	}
}

Uniform Handling Of Exceptions (Good)

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
	        throw new RuntimeException(exception);
	    }
	}

}

Uniform Handling Of Exceptions (Bad)

public class FilePrinterTest {
	private static final String invalidFileName = "";
	public void testInstantiateAndPrint() {
	    FilePrinter fpt = null;
	    try {
	        fpt = new FilePrinter(invalidFileName);
	        fpt.printFile();
	    } catch(Exception e) {
	        // handle all exceptions the same way
	        throw new RuntimeException(e);
        } catch(IllegalArgumentException iae) {
            throw new RuntimeException(iae);
        }
    }

    public void parseIntegerInput(String s) {
        try {
            Long.parseLong(s);
        } catch(NumberFormatException e) {
            throw new IllegalArgumentException(e);
        }
    }
}

Recursion and Exception Handling

Finally Keyword

Purpose

Conditions under which finally block is executed

  1. If no exception are thrown.
  2. If exception outside try block is thrown.
  3. If an exception is thrown in a catch clause.
  4. The program skips the finally clause, if the catch clause does not throw an exception.

Decoupling finally clause from try/catch clauses

class BookExample {
	public void example1() {
		InputStream in = ... ;
		try {
			try {
				// code that may throw exception
			} finally {
				in.close();
			}
		} catch(IOException ioe) {
			/// handle exception some way
		}
	}
}

Assertions

Toggling Assert Statements

When To Use

Logging

Principal advantages of Logging API

The 7 Logging Levels

Syntax

public class LogDemo {
	 // it is advised that you name your logger the same as your Main Application package
    Logger logger = Logger.getLogger("com.github.curriculeon.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
    }
}