LinesReaderAndPrinter.java |
package lectures.exceptions; import util.annotations.WebDocuments; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * EXCEPTIONS IN PROGRAMS INVOLVING MULTIPE METHODS * The previous example involved one method, which both performed * error-prone operations and handled the errors. * * It did not involve recovering from errors. * * Much of exception handling is about cooperative error handling/recovery * in multi-method programs. * * This is an example of a multi-method program, but it does not involve cooperative * multi-method processing or much error recovery. Each method processes the * exceptions thrown when it does its job. Is this the best strategy? * * Look at the program and follow the instructions after main. * * */ @WebDocuments({"Lectures/Exceptions.pptx", "Lectures/Exceptions.pdf", "Videos/Exceptions.avi"}) public class LinesReaderAndPrinter { /* * BufferedReader is an alternative to Scanner that better suits our purpose * as it throws an important Java exception, IOException, that we will study here. * The readLine() method of the class takes the place of the Scanner nextLine() method. * */ static BufferedReader input = new BufferedReader( new InputStreamReader(System.in)); /** * Delegates work to two methods, each of which can result in errors. */ public static void main (String args[]) { try { /* * set break point below */ echoLines(numberOfInputLines(args)); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Catch block in main executed"); } } /** * Reads from the console the number of lines specified in the argument * and echoes each of them to the console. * * Possible error: the user may not enter the expected number of lines. * For instance, the expected number is 2 and the user entered one and * then entered the EOF (End-of-File) character to close the console input. * * This method can be called from main or some other method. So it does * not know the context - that its argument is specified by the end * user as a main argument. */ public static void echoLines (int numberOfInputLines) { try { for (int inputNum = 0; inputNum < numberOfInputLines; inputNum++) { System.out.println("Please enter the line to be echoed"); System.out.println(input.readLine()); } } catch (IOException e) { // User entered the EOF (End of File) marker to close input // before the read was executed System.out.println("Did not input " + numberOfInputLines + " input strings before input was closed. "); } } /** * Determines the number of lines to be echoed by converting the * zeroth main argument into an int. * * Possible error: The user does not enter the main argument, as in the previous * example. * * Another error: The user does not specify a String that can be converted into an int. * We will ignore this error. * * Like the previous method, it can be called from main or some other method. * So it does also does not know the context - that its result will be used * in an interactive session by an end-user to echo lines. * * Is returning 0 the best error "recovery" strategy? * * Can you think of a better one, if the method had context and knew * what main was doing? * */ public static int numberOfInputLines(String[] args) { try { return Integer.parseInt(args[0]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Did not enter an argument"); return 0; } } } /* * EXCEPTIONS IN PROGRAMS INVOLVING MULTIPE METHODS * * Set the breakpoint in main. * * Debug-run the program with no argument, and use step into, step return and step over to * follow the program execution. * * (T/F) LinesReaderAndPrinter with no argument executes (one or more statements in) a try * block of numberOfInputLines. * * (T/F) LinesReaderAndPrinter with no argument executes a catch block of numberOfInputLines. * * * (T/F) LinesReaderAndPrinter with no argument executes (one or more statements in) a catch * block of main. * * (T/F) If method p calls method q, and the execution of q results in an exception * of type E that is handled by a catch block of q, then control transfers to a * catch block of q that can handle an exception of type E. * * (T/F) LinesReaderAndPrinter with no argument executes (one or more statements in) a try * block of echoLines. * * (T/F) LinesReaderAndPrinter with no argument executes a catch block of echoLines. * * (T/F) LinesReaderAndPrinter with no argument prompts the user for input. * * Now debug-run the program with an argument of 2 and follow the program * execution. Respond to the prompt in the console. * * (T/F) LinesReaderAndPrinter with an argument of 2 executes (one or more statements in) a try * block of numberOfInputLines. * * (T/F) LinesReaderAndPrinter with an argument of 2 executes a catch * block of numberOfInputLines. * * (T/F) LinesReaderAndPrinter with an argument of 2 executes (one or more statements in) a try * block of echoLines. * * (T/F) LinesReaderAndPrinter with an argument of 2 executes a catch * block of echoLines. * * * * In this example, is the operation that first detects an error the right one to * (completely) handle it? * * If not what do you need from Java to separate detection * and handling and to provide error handling involving multiple methods? * * * Go to {@link LinesReaderAndPrinterPropagatingExceptions} * */