mypages.valdosta.edu · web viewyou might want to refer to the exception hierarchy shown in the...

22
CS 1302 – Lab 05 This is a tutorial on exceptions. There are 7 stages to complete this lab: Stag e Title Text Reference 1 Understanding Exceptions and try/catch 12.1-12.2 2 try/catch Example 12.1-12.2 3 Throwing an Exception 12.4 4 Catching Multiple Types of Exceptions 12.4 5 Rethrowing & Chaining Exceptions 12.7-12.8 6 The finally Clause 12.5 7 Custom Exceptions 12.9 To make this document easier to read, it is recommend that you turn off spell checking in Word: 1. Choose: File, Option, Proofing 2. At the very bottom, check: “Hide spelling errors…” and “Hide grammar errors…” Stage 1 - Understanding Exceptions and try/catch In this stage you will learn about exceptions and using the try/catch block. You will not write any code in this stage. 1. Read (no action required) – When your code tries to do something illegal (e.g. divide by zero, call a method on an object that is null) a run-time error occurs and an Exception is thrown as shown in the class diagram below. If this exception is not caught (handled) then the program terminates. Java defines the Exception class. Subclasses (e.g. ArithmeticException, etc. ) correspond to specific types of errors that can occur in the program. For example, if you try to divide by zero, an ArithmeticException occurs. Similarly, if you try to access a position in a string that doesn’t exist, a StringIndexOutOfBoundsException occurs. 1

Upload: others

Post on 20-Jan-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: mypages.valdosta.edu · Web viewYou might want to refer to the exception hierarchy shown in the class diagram on the first page of this lab. Conversely, the code on the right below

CS 1302 – Lab 05

This is a tutorial on exceptions. There are 7 stages to complete this lab:

Stage Title Text Reference1 Understanding Exceptions and try/catch 12.1-12.22 try/catch Example 12.1-12.23 Throwing an Exception 12.44 Catching Multiple Types of Exceptions 12.45 Rethrowing & Chaining Exceptions 12.7-12.86 The finally Clause 12.57 Custom Exceptions 12.9

To make this document easier to read, it is recommend that you turn off spell checking in Word:

1. Choose: File, Option, Proofing2. At the very bottom, check: “Hide spelling errors…” and “Hide grammar errors…”

Stage 1 - Understanding Exceptions and try/catch

In this stage you will learn about exceptions and using the try/catch block. You will not write any code in this stage.

1. Read (no action required) – When your code tries to do something illegal (e.g. divide by zero, call a method on an object that is null) a run-time error occurs and an Exception is thrown as shown in the class diagram below. If this exception is not caught (handled) then the program terminates. Java defines the Exception class. Subclasses (e.g. ArithmeticException, etc.) correspond to specific types of errors that can occur in the program. For example, if you try to divide by zero, an ArithmeticException occurs. Similarly, if you try to access a position in a string that doesn’t exist, a StringIndexOutOfBoundsException occurs.

1

Page 2: mypages.valdosta.edu · Web viewYou might want to refer to the exception hierarchy shown in the class diagram on the first page of this lab. Conversely, the code on the right below

2. Read (no action required) – For example, consider the code below which calls inverse(0) and the inverse method attempts to divide 1 by 0 which results in an ArithmeticException and the program terminates. The Console window shows the exception that was thrown and then the sequence of statements that lead to the exception. For example, as shown in the figure below, line 11 was where the exception was thrown and line 7 was the call to the method.

3. Read (no action required) – Java defines a try/catch block that is used to catch exceptions so that the code does not terminate when an exception is thrown. As shown below, you put code that might fail in the try block and code to recover from the failure in the catch block.

try {// Code that may fail

}catch(Exception e) {

// Code to recover from failure}

2

Page 3: mypages.valdosta.edu · Web viewYou might want to refer to the exception hierarchy shown in the class diagram on the first page of this lab. Conversely, the code on the right below

4. Read (no action required) – Consider the code shown below on the right and the description of the numbered steps on the left. This code illustrates the use of a try/catch block to catch an exception.

Step Description1 inverse is called with the

argument 02 An attempt is made on

line 16 to divide by 03 An ArithmeticException is

thrown and is caught on line 10

4 A message is printed

5. Read (no action required) – Consider the code shown below on the right and the description of the numbered steps on the left. This is the same code as above (except that x=4), however no exception is thrown. Notice that the catch block is not activated when no exception is thrown.

Step Description1 inverse is called with the

argument 42 At line 16, 1 is divided by

4.3 The value (0.25) is

returned.4 The value is printed

3

Page 4: mypages.valdosta.edu · Web viewYou might want to refer to the exception hierarchy shown in the class diagram on the first page of this lab. Conversely, the code on the right below

Stage 2 - try/catch Example

In this stage we provide a simple example of using try/catch.

6. Do the following:

a. Establish a Workspace – Create a folder on your drive where you will put your lab or use an existing one.b. Run Eclipse – As the program begins to run, it will ask you to navigate to the Workspace you want to use.c. Create a Project – Create a Java project with the name, lab05_lastNameFirstInitial, e.g. lab05_gibsond.

7. Do the following:

a. Create a package named exception_examples1.b. Create a class named Example1 and replace everything in the class (except the package statement at the

top) with:

public class Example1 {

public static void main(String[] args) {char c = getCharAt("help", 8);System.out.println( c );

}

public static char getCharAt(String msg, int pos) {return msg.charAt(pos);

}}

c. Run and observe the output.

8. Add these lines to the beginning of main:

System.out.println("Answers:");System.out.println("a. ??? ");System.out.println("b. ??? ");System.out.println("c. ??? ");System.out.println("d. ??? ");

Answer the four questions below by replacing the “???”’s in the code above with your answers.

a. What is the class of the exception that is thrown?b. What caused this exception to be thrown (e.g. what was the programming error)?c. The output is similar to below. What do the last two links show?

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 8

at java.lang.String.charAt(Unknown Source)at lab4.Problem1.getCharAt(Problem1.java:11)at lab4.Problem1.main(Problem1.java:6)

4

Page 5: mypages.valdosta.edu · Web viewYou might want to refer to the exception hierarchy shown in the class diagram on the first page of this lab. Conversely, the code on the right below

d. Does this line in main:

System.out.println( c );

get executed? Rerun or use the debugger if necessary. Why or why not?

9. Do the following:

a. Create a class named Example2 and replace everything in the class (except the package statement at the top) with:

public class Example2 {

public static void main(String[] args) {char c;try {

c = getCharAt("help", 8);System.out.println("Got the answer!");

}catch(RuntimeException e) {

System.out.println("Exception:\n " + e);c = '*';

}System.out.println( "Character is: " + c );

}

public static char getCharAt(String msg, int pos) {return msg.charAt(pos);

}}

b. Run the code and verify the output.

c. Set a breakpoint on line 8:

c = getCharAt("help", 8);

d. Start the debugger and step into the code (F5). Carefully trace the code execution. Note the following:

i. An exception is thrown and after the catch block has finished, line 15 is executed:

System.out.println( "Character is: " + c );

This illustrates that program execution resumes with the statement immediately following a catch block (unless the exception is rethrown, we will discuss this later).

ii. Line 9 is never executed:

System.out.println("Got the answer!");

5

Page 6: mypages.valdosta.edu · Web viewYou might want to refer to the exception hierarchy shown in the class diagram on the first page of this lab. Conversely, the code on the right below

10. Do the following:

a. Make the changes shown on the right to your code. You will get a compile error, we discuss that next.

b. Add these lines to the beginning of main:

System.out.println("Answers:");System.out.println("i. ??? ");System.out.println("ii. ??? ");System.out.println("iii. ??? ");

Answer the questions below by replacing the “???”’s in the code above with your answers.

i. Why doesn’t the code compile?ii. True or False: A variable declared inside a try block can only be used inside the try block.

iii. Fill in the blank: Suppose a variable is used inside a try block. If you need to use that variable outside the try/catch block then it must be declared _____ (inside or outside) the try/catch block.

c. Reverse the changes you made in step a immediately above (so the code is in its original state and compiles). Run, and verify that your answers appear.

Stage 3 - Throwing an Exception

In this stage we show how to explicitly throw an exception

11. (Read, no action required) – Java allows the programmer to throw an exception. For example, suppose we have a Dog class whose constructor requires a name as an argument and that we require that the name be at least 2 characters long. One way to enforce this to have the Dog constructor throw an exception if the name is not 2 or more characters long. For example:

throw new IllegalArgumentException(“…description…”);

or

throw new RuntimeException(“…description…”);

Which type of exception should you throw? In the example above we said the Dog constructor accepted a name parameter that was subject to constraints. Thus, it makes sense to throw an IllegalArgumentException which is a subclass of RuntimeException. In other cases, the condition might not fit neatly into one of Java’s RuntimeException subclasses so we might just throw a RuntimeException. Alternately, we can create our own custom exception class that extends RuntimeException. We will consider this later in this lab.

6

Page 7: mypages.valdosta.edu · Web viewYou might want to refer to the exception hierarchy shown in the class diagram on the first page of this lab. Conversely, the code on the right below

12. Do the following:

a. Create a class named Dog and replace everything in the class (except the package statement at the top) with:

public class Dog {private String name;public Dog(String name) {

if( name.length() < 2) {throw new IllegalArgumentException("Name length must be 2 or

more");}else {

this.name = name;}

}

@Overridepublic String toString() {

return "Dog's name is: " + name;}

public static void main(String[] args) {Dog d;try{

d = new Dog("a");System.out.println(d);

}catch(RuntimeException e){

System.out.println(e);}System.out.println("Program over!");

}}

b. Study the code above carefully. Then, run and verify the output.

c. Change the argument “a” in main to a name that is 2 or more characters long. Then, run and verify the output.

7

Page 8: mypages.valdosta.edu · Web viewYou might want to refer to the exception hierarchy shown in the class diagram on the first page of this lab. Conversely, the code on the right below

Stage 4 - Catching Multiple Types of Exceptions

In this stage we show how to catch multiple different types of exceptions.

13. (Read, no action required) –

a. Java allows the try block to be followed by multiple catch blocks in order to catch different types of exceptions and handle them differently. Only one catch block will activate, however, the first one that matches. For example:

try { statements; // Statements that may throw exceptions}catch (Exception1 exVar1) { // handler for exception1;}catch (Exception2 exVar2) { // handler for exception2;}...catch (ExceptionN exVar3) { // handler for exceptionN;}

b. The compiler forces you to arrange the catch blocks from most specific to most general. For example, the code on the left below is valid because ArithmeticException (more specific) is a subclass of RuntimeException (more general). You might want to refer to the exception hierarchy shown in the class diagram on the first page of this lab. Conversely, the code on the right below is invalid (compile error) because RuntimeException is more general than ArithmeticException.

Valid Invalidtry {

divide(1,2);}catch ( ArithmeticException e ) {

// handler...}catch ( RuntimeException e ) {

// handler...}

try {divide(1,2);

}catch ( RuntimeException e ) {

// handler...}catch ( ArithmeticException e ) {

// handler...}

8

Page 9: mypages.valdosta.edu · Web viewYou might want to refer to the exception hierarchy shown in the class diagram on the first page of this lab. Conversely, the code on the right below

14. Do the following:

a. Create a class named MultipleCatches and replace everything in the class (except the package statement at the top) with:

public class MultipleCatches {

static int[] vals = new int[] {2,4,0,6};

public static void main( String[] args) {

try {divide(1,2);

}catch ( ArithmeticException e ) {

System.out.println( "Caught ArithmeticException: " + e );}catch ( RuntimeException e ) {

System.out.println( "Caught RuntimeException: " + e );}

}

public static int divide(int i, int j) {return vals[i]/vals[j];

}}

b. Study the code above carefully. Then, run and verify the output.

c. Change the line in main: divide(1,2); to: divide(1,42);. Then, run and verify the output.

Note: This time the second catch block activates. Thus, we have caught a RuntimeException but notice that when we print e, the actual exception, it is an instance of ArrayIndexOutOfBoundsException. The code throws an ArrayIndexOutOfBoundsException which is not an ArithmeticException, so the first catch block does not activate. However, ArrayIndexOutOfBoundsException is a subclass of RuntimeException so the second catch block activates. This can be tricky to understand. Use the debugger if necessary for each of these two cases to verify which catch block is being executed.

9

Page 10: mypages.valdosta.edu · Web viewYou might want to refer to the exception hierarchy shown in the class diagram on the first page of this lab. Conversely, the code on the right below

Stage 5 - Rethrowing & Chaining Exceptions

In this stage we show how to rethrow an existing exception that has been caught, or to chain it to a new exception and throw the new one.

15. (Read, no action required) – Consider the code shown on the right below and the explanation of the number steps on the left. The new concept is that on line 19 we catch an exception and then rethrow it on line 20..

Step Description1 main calls method12 method1 calls method23 method2 throws an exception

on line 26 which is caught by method1 on line 19

4 method1 rethrows the exception on line 20 which is caught by main on line 10

16. Do the following:

a. Create a class named RethrowChaining and replace everything in the class (except the package statement at the top) with:

public class RethrowChaining {public static void main( String[] args) {

try {method1();

}catch ( RuntimeException e ) {

System.out.println( "Caught in main:\n " + e );}

}public static void method1() {

try{method2();

}catch(RuntimeException e) {

throw e;}

}public static void method2() {

throw new RuntimeException("originated in method2()");}

}10

Page 11: mypages.valdosta.edu · Web viewYou might want to refer to the exception hierarchy shown in the class diagram on the first page of this lab. Conversely, the code on the right below

b. Study the code above carefully. Then, run and verify the output.

c. Set a breakpoint on the call to method1, start the debugger, step into the method call and carefully trace the execution.

17. (Read, no action required) –

a. All exception classes have an overloaded constructor that accepts two arguments: a description of the error and another exception. In this way exceptions can be chained together. Scroll back and look at method1. In the next step, we will replace:

throw e;

with:

throw new RuntimeException("originated in method1()", e);

Thus, the exception that was caught, e which originated in method2 will be chained to the new exception that is being created and thrown in method1.

b. Scroll back and look at main above. In the catch block we will add another print statement to also print the chained exception which is contained in e.getCause.

System.out.println( "Caught in main:\n " + e );System.out.println( "Chained exception:\n " + e.getCause() );

The result will be:

Caught in main: java.lang.RuntimeException: originated in method1()Chained exception: java.lang.RuntimeException: originated in method2()

18. Do the following:

a. Comment out the line of code in the catch block of method1 and replace with:

throw new RuntimeException("originated in method1()", e);

b. Add this line to the bottom of the catch block in main:

System.out.println( "Chained exception:\n " + e.getCause() );

c. Run and verify the output.

d. Add this line to the bottom of the catch block in main:

System.out.println( "\nException's stack trace:\n" );e.printStackTrace();

e. Run and verify the output. Note that the stack trace shows the path of execution of the main exception and the chained exception.

11

Page 12: mypages.valdosta.edu · Web viewYou might want to refer to the exception hierarchy shown in the class diagram on the first page of this lab. Conversely, the code on the right below

Stage 6 - The finally Clause

In this stage we consider the finally clause which can be used with a try/catch block.

19. (Read, no action required) –

a. Java provides an optional finally clause for try/catch. Code in the finally block always executes.

try {// Code that may fail}catch(Exception e) {// Code to recover from failure}finally {// Code that is always executed}

b. Consider the code shown on the right below which calls a method to divide to number. The explanation of the numbered steps is shown on the left.

Step Description1 divide is called on

line 72 Attempt to divide by

zero on line 16, throws an exception which is caught on line 19

3 Before the exeception is thrown on line 20, the finally block is executed

4 Then, the catch block throws the exception which is caught by main on line 10.

12

Page 13: mypages.valdosta.edu · Web viewYou might want to refer to the exception hierarchy shown in the class diagram on the first page of this lab. Conversely, the code on the right below

c. This is the same example as the previous one except no exception is thrown because the two numbers can be successfully divided. It illustrates that finally is called even when no exception is thrown.

Step Description1 divide is called on

line 7 and the division is successful on line 16.

2 Before the return on line 17, the finally block is executed

3 Then, the return on line 17 is executed and z is returned to main on line 7.

20. Do the following:

a. Create a new class named RethrowFinally and replace everything in the class (except the package statement at the top) with:

public class RethrowFinally {

public static void main( String[] args) {try {

System.out.println("Value is: " + divide(17,0));}catch ( RuntimeException e ) {

System.out.println( "Caught in main:\n " + e );}

}

public static double divide(int x, int y) {try{

double z = x/y;return z;

}catch(RuntimeException e) {

throw e;}finally{

System.out.println("finally block " + "executed in divide");}

}}

13

Page 14: mypages.valdosta.edu · Web viewYou might want to refer to the exception hierarchy shown in the class diagram on the first page of this lab. Conversely, the code on the right below

b. Run and verify the output.

c. Change this line:

System.out.println("Value is: " + divide(17,0));

to:

System.out.println("Value is: " + divide(17,5));

d. Run and verify the output.

Stage 7 - Custom Exceptions

In this stage we consider creating custom exceptions by extending RuntimeException.

21. (Read, no action required) –

a. In some situations, it is useful to write our own customized exception classes. These are classes just like any other class (except that they extend Exception or its subclasses). Thus, we can provide properties and methods that contain useful information about the error. Then, the code that catches the customized exception can use those properties (and methods) to (perhaps) make more useful decisions about how to handle the error.

b. In the example that follows we will create a Bird class whose constructor requires that the name be at least 5 characters long. If the constructor detects that the name is too short, then a BirdException is thrown. The BirdException class is a custom exception class and encapsulates the length of the name that was too short.

c. We first examine the design of the BirdException class. First, we declare the class by extending RuntimeException:

public class BirdException extends RuntimeException{

Next, we define an instance variable to hold the length of the name.

private int nameLength;

The constructor accepts a description of the error (desc) and the length of the name (nameLength). First, it calls the superclass constructor to store the descriptions. Then, it stores the length of the name.

public BirdException(String desc, int nameLength) {super(desc);this.nameLength = nameLength;

}

Finally, we provide a method to obtain the length of the name.

public int getNameLength() {return nameLength;

}

14

Page 15: mypages.valdosta.edu · Web viewYou might want to refer to the exception hierarchy shown in the class diagram on the first page of this lab. Conversely, the code on the right below

d. Next, we consider how we use the BirdException. The Bird class constructor is:

public Bird(String name) {if( name.length() < 5) { throw new BirdException("Bird name length too short",

name.length());}else { this.name = name;}

}

The highlighted line shows how we create and throw an instance of the BirdException class.

e. Finally, we show how main will catch a BirdException and use it to call the getNameLength method.

try{b = new Bird("Yoyo");

}catch(BirdException be) {

System.out.println(be + be.getNameLength() );}

22. Do the following:

a. Create a new class named BirdException and replace everything in the class (except the package statement at the top) with:

public class BirdException extends RuntimeException{private int nameLength;

public BirdException(String desc, int nameLength) {super(desc);this.nameLength = nameLength;

}

public int getNameLength() {return nameLength;

}}

15

Page 16: mypages.valdosta.edu · Web viewYou might want to refer to the exception hierarchy shown in the class diagram on the first page of this lab. Conversely, the code on the right below

b. Create a new class named Bird and replace everything in the class (except the package statement at the top) with:

public class Bird {private String name;public Bird(String name) {

if( name.length() < 5) { throw new BirdException("Bird name length too short",

name.length());}else { this.name = name;}

}

@Overridepublic String toString() {

return "Bird's name is: " + name;}

public static void main(String[] args) {Bird b;try{

b = new Bird("Yoyo");}catch(BirdException be) {

System.out.println(be);String msg = "Name length must be at least 5 characters, ";msg += "your name was: " + be.getNameLength();System.out.println(msg);

}}

}

c. Study the code above carefully and then run and verify the output.

You are done!

16