Exceptions If there is a problem with a Java statement, then a Java program may generate an exception or an error. Although an error represents an situation that the program can not recover from, an exception can be handled. Here are your three options when dealing with a thrown exception: 1) Not handle the exception 2) Handle the exception where it occurs 3) Handle the exception at another point in the program. Option #1 If you choose not to handle an exception, your program will terminate abnormally and produce an error message telling you which statement caused the exception to be thrown. This message is very helpful for debugging purposes. It will print out a call stack trace that tells you exactly which line in which method caused the exception. This printout includes the entire set of method calls leading to the exception. (e.g. main called func1 which called parseInt, which threw an exception.) Option #2 In order to handle an exception, we must use the try statement. Here is the syntax of the try statement: try { <stmts> } catch (<Class> <var>) { <exp_stmts> } You may have more than one catch clause. (You can have 0 or more.) Also, you may have a finally clause, but this must go at the end: try { <stmts> } catch (<Class> <var>) { <exp_stmts> } finally { <fin_stmts> } If the statements inside of the try block execute normally, then execution skips to the finally block after finishing the try block. (If not finally block exists, then execution skips to right after the last catch block.) However, if one of the statements in the try block throws an exception, then the rest of the statements in the try block are NOT executed. Rather, the class of the exception is noted. If this matches any of the catch clauses, then execution is transferred to the appropriate catch block. After that code is executed, execution transfers to directly after the last catch block. The whole benefit of catching an exception is that you allow your program to continue even if a line of code has throw an exception. Example: boolean done = false; int x; while (!done) { try { System.out.println("Enter an integer."); x = Integer.parseInt(stdin.readLine()); done = true; } catch (NumberFormatException exception) { System.out.println("Sorry, try entering an int!"); } } This piece of code will continue to prompt the user for an integer until they enter a valid one. Notice that without the try and catch in the while loop, this program would terminate after the first time data of the wrong format was entered. Notice that a block of code may have the possibility of throwing more than one exception. This is why you may have mutliple catches after a try block. Finally clause Execution is ALWAYS transferred to the finally clause whether an exception was thrown or not. It is executed last. Exception Propogation If an exception is not caught immediately in the method that it is thrown, the method will propogate or throw the exception to its calling method. It is possible them for this calling method to handle the exception. The example in the text (ppg. 384 - 6) does an excellent job of showing the mechanics of a propogated exception. Essentially, in this example, we have 1) Main calls method level1. 2) level1 calls method level2 inside of a try block. 3) level2 calls method level3. 4) A statement in level3 throws an exception that is not caught. 5) The exception is propogated back to level2. 6) Since level2 doesn't handle the exception, it's propogated to level1 7) level1 handles the exception by printing out some pertinent information about the exception. Notice from the code that each exception class has the methods getMessage() and printStackTrace(). These are (I believe) abstract methods in the Exception class. All exception classes inherit from this class. You can create your own exceptions (a class for each exception). However, I will not get into this since we are only spending one class on exceptions and files. Checked vs. Unchecked Exceptions: A checked exception MUST BE caught or listed in the throws clause of a method that may throw it. An unchecked one should not be caught. Reading from an Input File In order to read from a file, as opposed to the keyboard, you need to initialize a BufferedReader object with a FileReader object. Here is an example of how to set up a BufferedReader object to read from a file: BufferedReader infile = new BufferedReader (new FileReader("input.txt")); Now, if you want to read something from a file, use the infile object: String x = infile.readLine(); If you look at the example in the text on page 398, you can see how to gracefully take care of a "file not found" exception. Files are very important with respect to practical computer programs. It is often inefficient to type in all the input a computer program needs to accomplish it's task. Rather, it is quicker and less painful to process input from a file, especially when this input is lengthy. Writing to a Text File In order to do this, you must create a BufferedWriter object. This will look similar to the BufferedReader for reading from a file: BufferedWriter outfile = new BufferedWriter (new FileWriter("output.txt")); Now, you can use the outfile object to write to the output.txt file. The method you will use from the BufferedWriter class is the write method. It takes in a string as a parameter. Also, if you want, you may use the PrintWriter class which gives you more functionality than the BufferedWriter class. The example code I am handing out shows an entire application using files. The only information you need to understand this code are two methods in the Encrypter and Decrypter classes: public Encrypter(String pwd); //Constructor for an encrypter //takes in the password. public String encrypt(String word) //takes in a plaintext string //are returns a the //corresponding ciphertext //string Corresponding methods exist for the Decrypter class.