10.6 SOME USAGE PATTERNS FOR EXCEPTION HANDLING IN JAVA


10.6 SOME USAGE PATTERNS FOR EXCEPTION HANDLING IN JAVA

Usage Pattern 1:

The first usage pattern shown below is probably the most straightforward example of exception handling in Java. The class MyException is provided with two constructors in lines (B) and (C). The constructor in line (C) makes use of the base class's facility for storing a message that can be packed with the object of a throw. Since a class with any constructors at all is not provided with a system-supplied no-arg constructor, so we have defined one in (B) to construct a throw object without a message. In line (D), the function f is written so as to throw an exception of type MyExceptionx. This function is invoked in a try-catch block in line (E). The catch block traps the exception if it is thrown and, in line (F), recovers the message if one was packed with the object thrown.

 
//ExceptionUsage1.Java class MyException extends Exception { //(A) public MyException() { //(B) super(); } public MyException( String s ) { //(C) super( s ); } } class Test { static void f() throws MyException { //(D) throw new MyException( "Exception thrown by function f()"); } public static void main( String[] args ) { try { f(); //(E) } catch( MyException e) { System.out.println( e.getMessage()); //(F) } } }

Usage Pattern 2:

As this example shows, it is not necessary for a function that contains a throws clause in its header to actually throw that exception. Although there is no real reason for including the throws clause in the header of a function if it is not going to throw the exception, it is useful to know that Java gives you this freedom. The throws clause in the function header could be a part of the exception specification of a class as supplied by a vendor. A specific implementation of the function would dictate whether or not the function would actually throw that exception.

 
//ExceptionUsage2. java class MyException extends Exception {} class Test { static void f() throws MyException {} public static void main(String[] args) { try { f (); } catch (MyException e) {} } }

Usage Pattern 3:

A function can be written as to throw multiple exceptions, as the following example demonstrates. The function f in line (A) has been defined to throw two different exceptions, in lines (B) and (C), in response to two different circumstances during program execution.

 
//ExceptionUsage3.java class MyException extends Exception {} class Err extends Exception {} class Test { static void f(int j) throws MyException, Err { //(A) if (j == 1) throw new MyException(); //(B) if (j == 2) throw new Err(); //(C) } public static void main( String[] args ) { try { f( 1 ); } catch( MyException e ) { System.out.println("caught MyException -- arg must be 1"); } catch(Err e) { System. out. println("caught Err -- arg must be 2"); } try { f2); } catch( MyException e ) { System. out. println ("caught MyException -- arg must be 1"); } catch ( Err e ) { System. out. println ("caught Err -- arg must be 2"); } } }

Note that when a function is written as to throw multiple exceptions, they must all be mentioned in a comma separated list in the header of the function, as shown in line (A).

Usage Pattern 4:

The function h() in line (C) below invokes two separate functions, f and g, each capable of throwing a different exception, as shown by the code in lines (A) and (B). The function h must either trap these exceptions by invoking f and g inside trycatch blocks, or declare the exceptions in its header for re-throw. In the example code shown, we have chosen the latter option. Of course, we must trap the exceptions when h is called in line (D).

 
//ExceptionUsage4.java class MyException extends Exception {} class Err extends Exception {} class Test { static void f() throws MyException { //(A) throw new MyException(); } static void g() throws Err { //(B) throw new Err(); } static void h() throws MyException, Err { //(C) f(); g(); } public static void main(String[] args) { try { h(); //(D) } catch( MyException e ) { System.out.println("caught MyException"); } catch(Err e) { System.out.println( "caught Err"); } } }

Usage Pattern 5:

We will now show the importance of the finally clause. As was mentioned earlier, the finally clause is used for executing those steps that must be carried out whether or not an exception is thrown. Ordinarily, the flow of execution inside a function halts at the point an exception is thrown and the control shifts to the right brace of the try block in the calling function. The exception thrown by the called function would presumably be caught or re-thrown by the calling function. In either case, we may want to execute some clean-up operations.

In the example code below, the following functions throw the exceptions shown:

FileReader constructor

--

throws FileNotFoundException

read()

--

throws IOException

close()

--

throws IOException

In the code shown below, let's say that the statement in line (A) is executed successfully and the input stream object created. But now, let's assume that some exceptioncausing situation can arise in the while loop that starts at line (B). We have simulated such a problem by invoking foo() in line (C). The question now arises as to how to close the opened input stream. We could close the stream in an appropriate catch block. But that would not work if the exception is not thrown. You see, we wish for the opened stream to be closed in both cases-when an exception is thrown and when a problem function like foo() does not get invoked. We therefore stick the statement to close the stream in the finally clause. The code in that clause gets executed regardless of whether all of the code in the try block is executed successfully, or whether an exception is thrown in any of the statements.

 
//ExceptionUsage5.java import java.io.*; class Test { static void foo() throws Exception { throw new Exception(); } static void bar() throws Exception { FileReader input = null; try { input = new FileReader( "infile" ); //(A) int ch; while ( ( ch = input.read() ) = -1 ) { //(B) if ( ch == ‘A' ) { System.out.println( "found it"); foo(); //(C) } } } finally { if ( input != null ) { input.close(); System.out.println("input stream closed successfully"); } } System.out.println("Exiting bar()"); //(D) } public static void main(String[] args) { try { bar(); } catch(Exception e) { System.out.println("caught exception in main"); } } }

Note that the statement in line (D) will not get executed if an exception is thrown in line (C). So we do not have the luxury of closing the input stream outside the try-finally construct shown.

This usage pattern also shows that a try block does not necessarily have to be followed by a catch block. A try block can be followed directly by a finally block, but then you must include a throws clause in the method header so that it can re-throw that exception.

Usage Pattern 6:

This example is a small variation over the examples shown earlier. The method g shown below catches and then re-throws the same exception-an exception of type MyException that is then eventually caught in main.

 
//ExceptionUsage6.java class MyException extends Exception {} class Test { static void f() throws MyException { throw new MyException(); } static void g() throws MyException { try { f(); } catch(MyException e) { System.out.println( "catching and re-throwing in g"); throw new MyException(); } } public static void main( String[] args ) { try { g(); } catch( MyException e) { System.out.println("caught MyException in main"); } } }

Usage Pattern 7:

The purpose of this example is to draw a reader's attention to the fact that one can pack additional functionality in a programmer-defined exception class over and above what is provided by the base class. This one can do with the help of data members for the programmer-defined exception class, as we show in the following example. The code shown uses a data member of type String that can be used to pack a message with the thrown object. (The example merely demonstrates the notion of additional functionality in a programmer-defined exception class. If all you want to do is to send a simple string back with the thrown object, you can use the base class Exception's string data member for that purpose, as we showed in the first usage pattern in this section.) The class MyException now has a data member called message in line (A) and a constructor in line (B). The constructor allows us to set the value of the data member as desired when a MyException object is constructed, as we do in line (C) below.

 
//ExceptionUsage7.java class MyException extends Exception { String message; //(A) public MyException( String mess ) { message = mess; } //(B) } class Test { static void f() throws MyException { throw new MyException( "Hello from f()"); //(C) } public static void main(String[] args ) { try { f(); } catch( MyException e ) { System. out.println( e. message ); } } }




Programming With Objects[c] A Comparative Presentation of Object-Oriented Programming With C++ and Java
Programming with Objects: A Comparative Presentation of Object Oriented Programming with C++ and Java
ISBN: 0471268526
EAN: 2147483647
Year: 2005
Pages: 273
Authors: Avinash Kak

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net