Presentation is loading. Please wait.

Presentation is loading. Please wait.

Object-Oriented Programming 95-712 MISM/MSIT Carnegie Mellon University Lecture 9: Exception Handling, I/O.

Similar presentations


Presentation on theme: "Object-Oriented Programming 95-712 MISM/MSIT Carnegie Mellon University Lecture 9: Exception Handling, I/O."— Presentation transcript:

1 Object-Oriented Programming 95-712 MISM/MSIT Carnegie Mellon University Lecture 9: Exception Handling, I/O

2 Today’s Topics Older, and more modern, strategies for error handling. Older, and more modern, strategies for error handling. Exception handling basics. Exception handling basics. Some exception details: Some exception details: –plain Exceptions vs. RuntimeExceptions –Exceptions containing information –Exception hierarchies What’s really practical using exceptions. What’s really practical using exceptions. An introduction to the Java I/O library. An introduction to the Java I/O library.

3 Exception Handling The compiler is supposed to report syntax errors, it but can’t discover many other types of errors: The compiler is supposed to report syntax errors, it but can’t discover many other types of errors: –casts to the wrong type –files that don’t exist –dividing by zero –indexing out of bounds –incorrect data formats –badly formed SQL queries –etc. etc. Unresolved, many of these errors prevent a program from continuing correctly. Unresolved, many of these errors prevent a program from continuing correctly.

4 Exception Handling We would like to be aware of these “exceptional” situations, in hopes of We would like to be aware of these “exceptional” situations, in hopes of –recovery –retrying –trying an alternate strategy –cleanup before exit –or, just finding out where the problem is! Nothing is more mystifying than a program that just “goes up in smoke”! Nothing is more mystifying than a program that just “goes up in smoke”!

5 Exception Handling Whadda I do now???

6 Exception Handling What shall we do now???

7 Exception Handling Ahh, I know what to do!

8 Strategies for Error Handling In the course of programming, we constantly test for situations that routinely arise. In the course of programming, we constantly test for situations that routinely arise. We include logic to deal with the possibilities (switch, if-else, etc.). We include logic to deal with the possibilities (switch, if-else, etc.). “Exceptional” situations are different. They are things that “should never happen”. “Exceptional” situations are different. They are things that “should never happen”. We expect our code will be free from bugs, but… We expect our code will be free from bugs, but… We’re usually wrong. We’re usually wrong.

9 Strategies for Error Handling Pre-testing the arguments to each function call. Pre-testing the arguments to each function call. Checking return values indicating error. Checking return values indicating error. Setting and checking global error variables. Setting and checking global error variables. These are not formal methods, not part of the programming language itself. These are not formal methods, not part of the programming language itself. They require programmer discipline (but so does the use of exceptions…). They require programmer discipline (but so does the use of exceptions…).

10 Example void workOnArray(double[] myArray, int otherInfo) { int i = 0; // complicated calculation of array index i, using otherInfo myArray[i] = 3.14159; // what if i is out of bounds? }

11 Example (cont.) int workOnArray(double[] myArray, int otherInfo) { int i = 0; // complicated calculation of array index i, using otherInfo if (i >= 0 && i < myArray.length) { myArray[i] = 3.14159; return 0; // indicating everything OK } else return -1; // indicating an error }

12 Potential Problem What if workOnArray() needs to return a value (say, a double)? What if workOnArray() needs to return a value (say, a double)? The “C” approach: values are returned through additional reference arguments in the method: The “C” approach: values are returned through additional reference arguments in the method: int workOnArray( int workOnArray(double[] myArray, int otherInfo, double returnValue) This quickly gets cumbersome.

13 Another Technique: Globals There are no true global variables in Java, but we “fake it” all the time. There are no true global variables in Java, but we “fake it” all the time. Write a class with static variables! Write a class with static variables! These are effectively available anywhere in a program, and could be used to signal error conditions. These are effectively available anywhere in a program, and could be used to signal error conditions.

14 Faking A Global Variable public class MyGlobal { static int indexError; MyGlobals() { } // indexError automatically initialized to 0 } void workOnArray(double[] myArray, int otherInfo) { int i = 0; // complicated calculation of array index i, using otherInfo if (i >= 0 && i < myArray.length) { myArray[i] = 3.14159; } else MyGlobal.indexError = -1; }

15 Three Important Issues Where should the tests be done? Where should the tests be done? –Before the array is “indexed into”? –By the array class itself? Where should the error be reported? Where should the error be reported? –Locally, or “further down” in the call stack? –Stroustrup says that authors of libraries can’t know their user’s contexts, so can’t know what to do. Who is responsible for adjudicating the error? Who is responsible for adjudicating the error? Exception handling in Java helps with these problems, but doesn’t completely solve them. Exception handling in Java helps with these problems, but doesn’t completely solve them.

16 GPTree Exception Example Child Nodes are added to a Binop like this: Child Nodes are added to a Binop like this: position values for Binop should only be 1 or 2, it’s an error otherwise. But we might decide later to add Ternop, so the abstract Node method should allow for values other than 1 or 2. position values for Binop should only be 1 or 2, it’s an error otherwise. But we might decide later to add Ternop, so the abstract Node method should allow for values other than 1 or 2. public void setChild(int position, Node n) { if (position == 1) lChild = n; else // not 1, so must be 2, right? rChild = n; }

17 Solution: Add an Exception Class public class GPTreeChildPositionException extends Exception { } public abstract class Node{ public abstract void setChild(int position, Node n) throws GPTreeChildPositionException ; : } public abstract class Binop extends Node { public void setChild(int position, Node n) throws GPTreeChildPositionException { if (position == 1) lChild = n; else if (position == 2) rChild = n; else throw new GPTreeChildPositionException(); } : }

18 Exceptions at Work public static void main(String[] args) { double[] data = {3.14, 2.78, 1.0}; Node root = randOperator(); Node n1 = randOperator(); try { // any place setChild() is called must be in a try block! n1.setChild(1, randConstOrVariable()); n1.setChild(3, randConstOrVariable()); // Unghh! an error! Node n2 = randOperator(); n2.setChild(1, randConstOrVariable()); n2.setChild(2, randConstOrVariable()); root.setChild(1, n1); root.setChild(2, n2); } catch(GPTreeChildPositionException e) { System.out.println("Caught a GPTreeChildPositionException"); }

19 Points to Note We included in setChild() statement throwing a We included in setChild() a statement throwing a GPTreeChildPositionException. So we must let the users of the method know this, by stating So we must let the users of the method know this, by stating setChild(int position, Node n) throws GPTreeChildPositionException We have to do this in the abstract superclass as well. We have to do this in the abstract superclass as well. If we don’t the compiler gives an “unreported exception” error. If we don’t the compiler gives an “unreported exception” error.

20 More Points The compiler insists any call to this method be “tested” by enclosing it in a try block, or else we get an “unreported exception” error. The compiler insists any call to this method be “tested” by enclosing it in a try block, or else we get an “unreported exception” error. This is the same error message, but for a slightly different reason (confusing?). This is the same error message, but for a slightly different reason (confusing?). If we do include a try block (which we must!), there has to be a corresponding catch block or finally clause. If we do include a try block (which we must!), there has to be a corresponding catch block or finally clause.

21 Even More Points All of this is true because our exception extended the Exception class. All of this is true because our exception extended the Exception class. If we extend RuntimeException instead, we don’t need to say throws, nor include try and catch blocks. If we extend RuntimeException instead, we don’t need to say throws, nor include try and catch blocks. RuntimeExceptions are special; the Java runtime system takes care of them automatically. RuntimeExceptions are special; the Java runtime system takes care of them automatically. This can be a real advantage. This can be a real advantage.

22 Exception vs. RuntimeException Here is the output when deriving from Exception: Here is the output when deriving from Exception: Caught a GPTreeChildPositionException Here is the result when implementing RuntimeException with no try-catch blocks: Here is the result when implementing RuntimeException with no try-catch blocks:GPTreeChildPositionException at Binop.setChild(Binop.java:17) at TestAlgebra.main(TestAlgebra.java:47) Exception in thread "main"

23 Exceptions Always Get Caught public class NeverCaught { static void f() { static void f() { throw new RuntimeException(“From f()”); throw new RuntimeException(“From f()”); } static void g() { static void g() { f(); f(); } public static void main(String[] args) { public static void main(String[] args) { g(); g(); }}

24 “Uncaught” Exceptions If an exception makes it all the way “back” to main() without being caught, the Java runtime system calls printStackTrace() and exits the program: If an exception makes it all the way “back” to main() without being caught, the Java runtime system calls printStackTrace() and exits the program: You can call printStackTrace() yourself if you want (and it’s useful to do it). You can call printStackTrace() yourself if you want (and it’s useful to do it). java.lang.RuntimeException: From f() at NeverCaught.f(NeverCaught.java:5) at NeverCaught.g(NeverCaught.java:8) at NeverCaught.main(NeverCaught.java:11) Exception in thread "main"

25 Call Stack, Normal Execution main() called main() f() called f() g() called f() g() g() finished f() f() finished time

26 Call Stack, With Exception main() called main() f() called f() g() called f() g() f() exception thrown, g() has no handler, exit g() search f() for handler, exit f() search main() for handler, call printStackTrace(), exit main()

27 Exceptions Containing Information Exceptions are real objects (created with new), and so can have constructors and data members. Exceptions are real objects (created with new), and so can have constructors and data members. public class GPTreeChildPositionException extends Exception { int i; GPTreeChildPositionException(){} GPTreeChildPositionException(String msg) { super(msg); } GPTreeChildPositionException(int i) { this.i = i; }

28 Using the Information try { n1.setChild(1, randConstOrVariable()); n1.setChild(3, randConstOrVariable()); // error Node n2 = randOperator(); n2.setChild(1, randConstOrVariable()); n2.setChild(2, randConstOrVariable()); root.setChild(1, n1); root.setChild(2, n2); } catch(GPTreeChildPositionException e) { System.out.println(“Caught a ” + “GPTreeChildPositionException, position = ” + e.i); }

29 Catching Any Exception We are always interested in exceptions that implement the interface Exception. We are always interested in exceptions that implement the interface Exception. So, a catch block like So, a catch block like catch(Exception e) { System.out.println(“Caught an exception”); System.out.println(“Caught an exception”);} will catch any exception. If you have multiple catch blocks, this one should be last. If you have multiple catch blocks, this one should be last.

30 Multiple Catch Blocks There may be several possible errors generated by a block of code: There may be several possible errors generated by a block of code: try { // try this // try this // and this // and this} catch( catch(GPTreeChildPositionException e) { System.out.println(“Caught child position exception”); } catch(Exception e) { System.out.println(“Caught some other exception”); }

31 Rethrowing an Exception Suppose you’ve caught an exception, and decided you can’t recover from it, but perhaps a higher context can. Suppose you’ve caught an exception, and decided you can’t recover from it, but perhaps a higher context can. You can rethrow it: You can rethrow it: catch(Exception e) { System.out.println(“An exception was caught”); System.out.println(“An exception was caught”); throw e; throw e;} The stack trace remains unchanged if it is caught higher up. The stack trace remains unchanged if it is caught higher up.

32 Catching, Fixing and Retrying public class Retry { static int i = 0; public void f() { try { g(); } catch(Exception e) { System.out.println("Caught exception, i = " + i); i++; f(); } void g() throws gException { if (i < 3) { throw new gException(); } else System.out.println("g() is working now"); }

33 This Can Be Dangerous public class Retry { int i = 0; boolean fileIsOpen = false; public void f() { try { if (fileIsOpen) System.out.println("Opening an already opened file!"); else fileIsOpen = true;// i.e., open the file g(); fileIsOpen = false;// i.e., close the file } // file will be left open: Dangerous!

34 What’s So Dangerous? Just close the file in the catch block? Good idea! But, what if some other exception were thrown, one that you didn’t catch? Just close the file in the catch block? Good idea! But, what if some other exception were thrown, one that you didn’t catch? catch(gException e) { System.out.println("Caught exception, i = " + i); i++; fileIsOpen = false; f(); } finally { fileIsOpen = false; }

35 Exception Hierarchies Exceptions are classes, so can be in inheritance hierarchies. Exceptions are classes, so can be in inheritance hierarchies. The usual polymorphism rules apply. The usual polymorphism rules apply. A handler for a superclass exception will catch a subclass exception. A handler for a superclass exception will catch a subclass exception. This makes it easy to catch groups of exceptions. This makes it easy to catch groups of exceptions.

36 The GPTree Hierarchy public class GPTreeException extends Exception { GPTreeException() { } GPTreeException(String msg) { super(msg); } public class GPTreeChildPositionException extends GPTreeException { int i; // constructors } public class GPTreeRandOpException extends GPTreeException { int i; // constructors }

37 Declare the New Exception public static Node randOperator() throws GPTreeRandOpException { Node n; int i = r.nextInt(5);// this is an error! switch(i) { case 0: n = new Plus(); break; case 1: n = new Minus(); break; case 2: n = new Mult(); break; case 3: n = new Divide(); break; default: throw new GPTreeRandOpException(i); } return n; }

38 Then Catch It As GPTreeException try { Node root = randOperator(); // add all the children String s = root.toString(); System.out.println(s + " = " + root.eval(data)); } catch(GPTreeChildPositionException e) { System.out.println(“Caught a ” + “GPTreeChildPositionException, position = ” + e.i); } catch(GPTreeException e) { System.out.println("Caught a GPTreeException"); }

39 Termination Vs. Resumption Java makes it hard to complete this cycle: Java makes it hard to complete this cycle: –find a problem, –throw an exception, –fix the problem in the handler, and –go back to where you left off. This is called “resumption”. This is called “resumption”. Java assumes you don’t want to go back. Java assumes you don’t want to go back. This is called “termination”. This is called “termination”.

40 What You Can Do Fix the problem and call the method that caused the exception once more. Fix the problem and call the method that caused the exception once more. “Patch things up” and continue without retrying the method. “Patch things up” and continue without retrying the method. Calculate some alternative result. Calculate some alternative result. Do what you can in the current context, and rethrow the same exception to a higher context. Do what you can in the current context, and rethrow the same exception to a higher context. Do what you can, and throw a different exception to a higher context. Do what you can, and throw a different exception to a higher context. Terminate the program (how?). Terminate the program (how?).

41 Java Input/Output I/O libraries are hard to design, and everyone can find something to complain about. I/O libraries are hard to design, and everyone can find something to complain about. Java’s I/O library is extensive, and it seems like you need to know 100 things before you can start using it. Java’s I/O library is extensive, and it seems like you need to know 100 things before you can start using it. Today, let’s learn just five things and still do something useful. Today, let’s learn just five things and still do something useful.

42 #1: Why Is Java I/O Hard? Java is intended to be used on many very different machines, having Java is intended to be used on many very different machines, having –different character encodings (ASCII, EBCDIC, 7- 8- or 16-bit…) –different internal numerical representations –different file systems, so different filename & pathname conventions –different arrangements for EOL, EOF, etc. The Java I/O classes have to “stand between” your code and all these different machines and conventions. The Java I/O classes have to “stand between” your code and all these different machines and conventions.

43 #2: Java’s Internal Characters Unicode. 16-bit. Good idea. Unicode. 16-bit. Good idea. So, the primitive type char is 16-bit. So, the primitive type char is 16-bit. Reading from a file using 8-bit ASCII characters (for example) requires conversion. Reading from a file using 8-bit ASCII characters (for example) requires conversion. Same for writing. Same for writing. But binary files (e.g., graphics) are “byte-sized”, so there is a primitive type byte. But binary files (e.g., graphics) are “byte-sized”, so there is a primitive type byte. So Java has two systems to handle the two different requirements. So Java has two systems to handle the two different requirements. Both are in java.io, so import this always! Both are in java.io, so import this always! I don’t show imports in the examples below. I don’t show imports in the examples below.

44 Streams Host Machine ASCII? EBSDIC? InputStream Class OutputStream Class Java Program Using Bytes These classes are tailored to a specific host machine. byte

45 Readers and Writers Host Machine ASCII? EBSDIC? InputStream Class OutputStream Class Java Program Using Unicode char Reader Class Writer Class

46 #3: Is Java “Platform Independent”? Yes, to the extent that you, the Java programmer, needn’t care about the platform your code will run on. Yes, to the extent that you, the Java programmer, needn’t care about the platform your code will run on. No, to the extent that the Java I/O classes, the compiler, and any browser your clients use, must be programmed specifically for the host machine. No, to the extent that the Java I/O classes, the compiler, and any browser your clients use, must be programmed specifically for the host machine. This is not a new idea, just well-hyped by Sun (recall “p-code” from the 1970’s). This is not a new idea, just well-hyped by Sun (recall “p-code” from the 1970’s).

47 #4: What Are The Input Sources? System.in, which is an InputStream connected to your keyboard. (System is public, static and final, so it’s always there). System.in, which is an InputStream connected to your keyboard. (System is public, static and final, so it’s always there). A file on your local machine. This is accessed through a Reader and/or an InputStream, usually using the File class. A file on your local machine. This is accessed through a Reader and/or an InputStream, usually using the File class. Resources on another machine through a Socket, which can be connected to an InputStream, and through it, a Reader. Resources on another machine through a Socket, which can be connected to an InputStream, and through it, a Reader.

48 #5: Why Can’t We Read Directly From These? We can, but Java provides only “low-level” methods for these types. For example, InputStream.read() just reads a byte… We can, but Java provides only “low-level” methods for these types. For example, InputStream.read() just reads a byte… It is assumed that in actual use, we will “wrap” a basic input source within another class that provides more capability. It is assumed that in actual use, we will “wrap” a basic input source within another class that provides more capability. This “wrapper” class provides the methods that we actually use. This “wrapper” class provides the methods that we actually use.

49 “Wrapping” Input comes in through a stream (bytes), but usually we want to read characters, so “wrap” the stream in a Reader to get characters. Input comes in through a stream (bytes), but usually we want to read characters, so “wrap” the stream in a Reader to get characters. public static void main(String[] args) { InputStreamReader isr = new InputStreamReader(System.in); int c; try { while ((c = isr.read()) != -1) System.out.println((char) c); } catch(IOException e) { }

50 InputStreamReader This is a bridge between bytes and chars. This is a bridge between bytes and chars. The read() method returns an int, which must be cast to a char. The read() method returns an int, which must be cast to a char. read() returns -1 if the end of the stream has been reached. Thus the program above will never stop, since we can’t type the “end-of- stream” value. read() returns -1 if the end of the stream has been reached. Thus the program above will never stop, since we can’t type the “end-of- stream” value. We need more methods to do a better job! We need more methods to do a better job!

51 Use a BufferedReader public static void main(String[] args) { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String s; try { while ((s = br.readLine()).length() != 0) System.out.println(s); } catch(IOException e) { }

52 “Transparent Enclosure” System.in (InputStream) InputStreamReader BufferedReader an abstract class adds read() “looks like” a Stream “looks like” a Reader adds readLine() and buffering “looks like” a Stream “looks like” a Reader

53 Reading From a File The same idea works, except we need to use a FileInputStream. The same idea works, except we need to use a FileInputStream. Its constructor takes a string containing the file pathname. Its constructor takes a string containing the file pathname. public static void main(String[] args) throws IOException { InputStreamReader isr = new InputStreamReader(new FileInputStream("FileInput.java")); int c; while ((c = isr.read()) != -1) System.out.println((char) c); isr.close(); }

54 Reading From a File (cont.) Here we check for a -1, indicating we’ve reached the end of the file. Here we check for a -1, indicating we’ve reached the end of the file. In Together, this works just fine, but an absolute path name is safer. In Together, this works just fine, but an absolute path name is safer. The read() method can throw an IOException, and the FileInputStream constructor can throw a FileNotFoundException The read() method can throw an IOException, and the FileInputStream constructor can throw a FileNotFoundException Instead of using a try-catch construction, this example shows main() declaring that it throws IOException. This is a “dirty trick”. Instead of using a try-catch construction, this example shows main() declaring that it throws IOException. This is a “dirty trick”.


Download ppt "Object-Oriented Programming 95-712 MISM/MSIT Carnegie Mellon University Lecture 9: Exception Handling, I/O."

Similar presentations


Ads by Google