Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
EXCEPTION HANDLING OR ERROR HANDLING 1 Agenda • • • • • • • Introduction Errors and Exception Exception Hierarchy Classification of Exceptions Built in Exceptions Exception Handling in Java User defined Exceptions Introduction “ An exception is a condition that cannot be resolved within the context of the operation that caused it. ” • To throw an exception is to signal that such a condition has occurred. • To catch an exception is to transfer control to an exception handling routine, altering the normal execution flow of the program. Questions • What is an Error? • What is the Difference between Error and Exception? Answers Error: “ An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. “ • Errors can not be caught. Examples: Stackoverflow and underflow Answers Exception: “The class Exception and its subclasses are a form of Throwable that indicates conditions that a reasonable application might want to catch. “ • Exception can be caught using key words such as try and catch block. Exceptions • Exceptions can occur at many levels: Hardware/operating system level Arithmetic exceptions; divide by 0, under/overflow. Memory access violations; stack over/underflow. Language level Program level Type conversion; illegal values, improper casts. Bounds violations; illegal array indices. Bad references; null pointers. User defined exceptions. Exception Example public class UnhandledException { public static void main(String[] args) { int num1 =0,num2 =5; int num3 = num2/num1; System.out.println(" Value = " +num3); } } What is Error? - Error means mistakes or buggs - Error is classified into types Error Compile Time Error All syntax errors will be detected And displayed by the Java compi ler and therefore these errors Are known as compile – time – errors 1. Missing Semicolon 2. Missing brackets in classes and methods 3. Use of undeclared variables Run Time Error A program may compile success fully creating the .exe file but not run properly. Such programs may produce wrong results due to wrong loaic or may terminate due to errors 1. Dividing an integer by zero 2. Accessing an element that is out of 9 the bounds of an array Exception Hierarchy Some Example of Runtime Errors class Error_Handling { public static void main(String args[]) { int a,b,c; a = 10; b = 0; c = a / b; System.out.println("The Value of the C Value is:" + c); } } Output: / by zero 11 Exception Types 1. All Exception types are subclasses of the built – in class Throwable. Throwable is at the top of the exception class hierarchy Throwable Exception (or) RuntimeException This class is used for exceptional conditions that user programs should catch. This is also the class That you will subclass to create your own custom exception types Error Which defines exceptions that are not Expected to be caught under normal Circumstances by our program. Ex. Stack overflow 12 Classification of Exceptions • Exceptions can be classified as Built-in Exceptions • These exceptions are define by Java and they reside in java.lang package . User-Defined Exceptions • Exceptions defined by users. Examples of Exception: NullPointerException ArrayIndexOutOfBounds Exception IOException Built-in Exceptions Built-in Exceptions in Java Checked Exception: Unchecked Exception: The invalid conditions that occur in java program due to invalid user input, database problems etc. • They are run time errors that occur because of programming errors such as invalid arguments passed to a public method. • Examples: • Examples: • IOException • SQLException • ArrayIndexOutOfBoundsException • NullPointerException Checked Exception Exception Name Description ClassNotFoundException Class not found InstantiationException Attempt to create an object of an abstract class or interface. IllegealAccessException Access to a class is denied. NoSuchMethodException A requested method does not exist. NoSuchFieldException A requested field does not exist. InterruptedException One thread has been interrupted by another thread. CloneNotSupportedException Attempt to clone an object that does not implement Cloneable interface. Unchecked Exception Exception Name Description ArithmeticException Arithmetic error, such as divide by zero. NegativeArraySizeException Array created with a negative size. NullPointerException Invalid use of a null reference. IllegealArgumentException Illegeal argument used to invoke a method. ClassCastException Invalid class cast ArithmeticException Arithmetic error, such as divide by zero. NegativeArraySizeException Array created with a negative size. Uncaught Exception class Error_Handling { public static void main(String args[]) { int i,j,k1,k2; i = 10; j = 0; k1 = i / j; k2 = i + j; System.out.println("The Division of the K1 Value is: " + k1); System.out.println("The addition of the K2 Value is: " + k2); } } Output: java.lang.ArithmeticException: / by zero at Error_Handling.main(Error_Handling.java:4) 17 the In this example, we haven’t supplied any exception handlers of our own, so exception is caught by the default handler provided by the java run – time system What is Exceptions? An Exception is condition that is caused by a run – time error in the program. What is Exception Handling? If the exception object is not caught and handled properly, the compiler will display an error message and will terminate the program. If we want the program to continue with the execution of the remaining appropriate message for taking corrective actions. This task is known as exception handling. Exceptions Types Exception Synchronous Exception 1. Division by Zero Asynchronous Exception 1. Keyboard Interrupt 2. Mouse Interrupt 18 Exception Handling Mechanism The purpose of the exception handling mechanism is to provide means to detect and report an “exceptional circumstance”, so that appropriate action can be taken. The Error Handling code that performs the following tasks: 1. Find the problem (Hit the Exception) 2. Inform that an error has occurred (Throw the exception) 3. Receive the error information (Catch the exception) 4. Take corrective actions (Handle the exception) try block Detects and throws an exception catch block Exception object Catches and handles the exception 19 Using try and catch ----------------------------------- try { ------------------------- ------------- //Block of statements which detects and //throws an exception } catch(Exception_Type e) //Catches exception { --------------------------- //Block of statements that handles the //exception } ----------------------------------- 20 Exception Handling in Java Exceptions in Java can be handled by five keywords Catch Try Throws Throw Finally Exception Handling in Java – Contd., TRY CATCH •used with the code that might throw an exception. • This statement is used to specify the exception to catch and the code to execute if the specified exception is thrown. FINALLY •is used to define a block of code that we always want to execute, regardless of whether an exception was caught or not. THROW • Typically used for throwing user-defined exceptions THROWS Exception • Lists the types of exceptions a method can throw, so that the callers of the method can guard themselves against the exception Exception Handling Mechanism • The basic concepts of exception handling are throwing an exception and catching it. Throws exception object Try Block Exception object creator Statement that causes an exception catch Block Statement that handles the exception Exception Handler Exception Handling syntax try { statements } catch (Exception class object) { statements } finally { //Close file handles //Free the resources } Try and catch public class TryCatchDemo { public static void main(String [] args) { int x,y; try { x = 0; y = 10/x; System.out.println(“Now What ???”); } catch(ArithmeticException e){ System.out.println(“Division by zero”); } TryCatchDemo System.out.println(“Hi I am back !!!”); } } Example Program for Exception Handling Mechanism class Error_Handling { public static void main(String args[]) { int i,j,k1,k2; i = 10; j = 0; try { There is an Exception k1 = i / j; System.out.println("The Division of the K1 Value is: " + k1); } catch(ArithmeticException e) Catches the exception { System.out.println("Division by Zero"); } k2 = i + j; System.out.println("The addition of the K2 Value is: " + k2); } } 26 Output: Division by Zero, The addition of the K2 Value is:10 Multiple Catch Statements It is possible that a program segment has more than one condition to throw an exception. try { //statements } catch(Exception-Type-1 e) { //statements } catch(Exception-Type-2 e) { //statements } --------------------catch(Exception-Type-N e) { //statements } 27 class Error_Handling { public static void main(String args[]) { int a[ ] = {5,10}; int b = 5; try { int x = a[2] / b - a[1]; } catch(ArithmeticException e) { System.out.println("Division by Zero"); } catch(ArrayIndexOutOfBoundsException e) { System.out.println("Array Index Error"); } catch(ArrayStoreException e) { System.out.println("Wrong data type"); } int y = a[1] / a[0]; System.out.println("Y = " + y); } } 28 COMMAN EXCEPTION HANDLER class Error_Handling { public static void main(String args[]) { int a[ ] = {5,10}; int b = 5; try { int x = a[2] / b - a[1]; } catch(ArithmeticException e) { System.out.println("Division by Zero"); } /*catch(ArrayIndexOutOfBoundsException e) { System.out.println("Array Index Error"); }*/ catch(ArrayStoreException e) { System.out.println("Wrong data type"); } 29 catch(Exception e) { System.out.println("The Producing any Runtime Error" + e.getMessage()); } int y = a[1] / a[0]; System.out.println("Y = " + y); } } 30 EXCEPTION HIERARCHY class Error_Handling { public static void main(String args[]) { int a[ ] = {5,10}; int b = 5; try { int x = a[2] / b - a[1]; } catch(ArithmeticException e) { System.out.println("Division by Zero"); } catch(Exception e) { System.out.println("The Producing any Runtime Error" + e.getMessage()); } /*catch(ArrayIndexOutOfBoundsException e) { System.out.println("Array Index Error"); }*/ 31 catch(ArrayStoreException e) { System.out.println("Wrong data type"); } int y = a[1] / a[0]; System.out.println("Y = " + y); } } 32 Nested try Statements class Error_Handling { public static void main(String args[]) { try { int a = args.length; int b = 42 / a; //If no command - line args are present, //the following statement will generate a divide - by - zero exception System.out.println("a = " + a); // nested try bloack // If one command - line arg is used, then a divide - by //- zero exception will be generated by the following code. 33 try { if ( a == 1) a = a / (a - a); //division by zero if(a == 2) { int c[] = {1}; c[42] = 99; //generate an out - of - bounds exception } } catch(ArrayIndexOutOfBoundsException e) { System.out.println("Array index out - of - bounds: " + e); } } catch(ArithmeticException e) { System.out.println("Divide by Zero: " + e); } } } 34 Nested try Statements using Subroutine class Error_Handling { static void nesttry(int a) { try { if ( a == 1) a = a / (a - a); //division by zero if(a == 2) { int c[] = {1}; c[42] = 99; //generate an out - of - bounds exception } } catch(ArrayIndexOutOfBoundsException e) { System.out.println("Array index out - of - bounds: " + e); } } 35 public static void main(String args[]) { try { int a = args.length; int b = 42 / a; //If no command - line args are present, the //following statement will generate a divide - by - zero exception System.out.println("a = " + a); // nested try bloack // If one command - line arg is used, then a divide - by //zero exception will be generated by the following code. nesttry(a); // Calling Static Method } catch(ArithmeticException e) { System.out.println("Divide by Zero: " + e); } } } 36 throw 1. You have only been catching exceptions that are thrown by the java run – time system. 2. However, it is possible for your program to throw an exception explicitly. Using throw statement. Syntax: throw ThrowableInstance; 1. Here, ThrowableInstance must be an object of type Throwable or a subclass of Throwable. 2. Simple types, such as int or char, as well as non – Throwable classes, such as String and Object, cannot be used as exception. 3. There are two ways you can obtain a Throwable object: using a parameter into a catch clause, or creating one with the new operator. 37 class Error_Handling { static void display() { try { throw new NullPointerException("Demo"); } catch(NullPointerException e) { throw e; } } public static void main(String args[]) { try { display(); } catch(NullPointerException e) { System.out.println("Recaught : " + e); } } } 38 throws 1. If a method is capable of causing an exception that it does not handle, it must specify this behavior so that callers of the method can guard themselves against that exception. 2. You do this by including a throws clause in the method’s declaration. A throws clause list the types of exceptions that a method might throw. 3. This is necessary for all exceptions, except those of type Error or RuntimeException, or any of their subclasses. All other exceptions that a method can throw must be declared in the throws clause. 4. If they are not, a compile – time error will result. type method-name (parameter-list) throws exception-list { //body of method } Here, exception – list is comma – separated list of the exceptions that a method can throw 39 class Error_Handling { static void throwdemo() throws IllegalAccessException { System.out.println("Inside throwdemo"); } public static void main(String args[]) { try { throwdemo(); } catch(IllegalAccessException e) { System.out.println("Caught " + e); } } } 40 Using finally Statement 1. Java supports another statement known as finally statement that can be used to handle an exception that is not caught by any of the previous catch statements. 2. finally block can be used to handle any exception generated within a try block. 3. It may be added immediately after the try block or after the last catch block. try { try { //statements } finally { ------------------------------------} //statements } catch(Exception-Type-1 e) { //statements } catch(Exception-Type-2 e) { //statements } --------------------catch(Exception-Type-N e) { //statements } finally { ------------------------------------} 41 Finally Block • • • • Ensures that all cleanup work is taken care of when an exception occurs Used in conjunction with a try block Guaranteed to run whether or not an exception occurs Syntax finally { // Blocks of code} No exception finally try block catch block finally Exception Finally Demo Rules for Try-Catch-Finally • For each try block there can be one or more catch block but only one finally block. • A finally block cannot execute without a try block. • Try block can be nested with catch blocks. Throw and Throws Keyword • "throws" declares that your method is capable of throwing an exception. • "throw" actually does the work , of throwing the exception. • Example : public void doSomething() throws ApplicationException { try{ } catch(Exception e){ // catch all excpetions here throw ApplicationException("An error occurred while trying connect to DB"); } } ThrowsAndThrowKeyWordDemo class Error_Handling { static void procA() { try { System.out.println("Inside ProcA"); throw new RuntimeException("demo"); } finally { System.out.println("ProcA's finally"); } } static void procB() { try { System.out.println("inside ProcB"); //return; } finally { System.out.println("ProcB's finally"); } } 45 static void procC() { try { System.out.println("inside ProcC"); } finally { System.out.println("ProcC's finally"); } } public static void main(String args[]) { try { procA(); } catch(Exception e) { System.out.println("Exception Caught"); } finally { System.out.println("Procedure A is Wind up"); } procB(); procC(); } } 46 Java’s Built – in Exceptions 1. The standard package java.lang, Java defines several exception classes. A few have been used by the preceding examples. 2. The most general of these exceptions are subclasses of the standard type RuntimeException. 3. Since java.lang is implicitly imported into all java programs, most exceptions derived from RuntimeException are automatically available. 4. Furthermore, they need not be included in any method’s throws list. 5. In the language of Java, these are called unchecked exceptions because the compiler does not check to see if a method handles or throws these exceptions. 6. The other exceptions defined by java.lang that must be included in a method’s throws list if that method can generate one of these exceptions and does not handle it itself. These are called checked exceptions. 47 Java’s Unchecked RuntimeException Subclasses Exception Meaning ArithmeticException Arithmetic error, such as divde – by – zero ArrayIndexOutOfBoundsException Array index is out – of – bounds. ArrayStoreException Assignment to an array element of an incompatible type. ClassCastException Invalid Cast. IllegalArgumentException Illegal argument used to invoke a method IllegalMonitoStateException Illegal Monitor Operation, such as waiting on an unlocked thread. IllegalStateException Environment or incorrect state. IllegalThreadStateException Requested operation not compatible with current thread state. IndexOutOfBoundsException Some type of index is out – of – bounds NegativeArraySizeException Array Created with a negative size. application is in 48 Exception Meaning NullPointerException Invalid use of a null reference. NumberFormatException Invalid conversion of a string to a numeric format. SecurityException Attempt to violate security StringIndexOutOfBounds Attempt to index outside the bounds of a string. UnsupportedOperationException An unsupported encountered. Operation was 49 Java’s Checked Exception Defined in java.lang Exception Meaning ClassNotFoundException Class not found CloneNotSupportedException Attempt to clone an object that does not implement the cloneable interface. IllegalAccessException Access to a class is denied InstantiationException Attempt to create an object of an abstract class or interface InterruptedException One thread has been interrupted by another thread. NoSuchFieldException A requested field does not exist. NoSuchMethodException A requested method does not exist. 50 Throwing our own Exceptions There may be times when we would like to throw our own exceptions. We can do this by using the keyword throw as follows: throw new Throwable_subclass; Example: throw new ArithmeticException(); throw new NumberFormatException(); Note: 1. Exception is subclass of Throwable and therefore MyException is a subclass of Throwable class. 2. An object of a class that extends Throwable can be thrown and caught 51 import java.lang.Exception; class MyException extends Exception { MyException(String message) { super(message); } } class Exception_Handling { public static void main(String args[]) { int x = 5, y = 1000; try { float z = (float) x / (float) y; if (z < 0.01) { throw new MyException("Number is too small"); 52 } } catch(MyException e) { System.out.println("Caught my exception"); System.out.println(e.getMessage()); } finally { System.out.println("I am always here"); } } } 53 Using Exceptions 1. Exception handling provides a powerful mechanism for controlling complex programs that have many dynamic run – time characteristics. 2. It is important to think of try, throw and catch as clean ways to handle errors and unusual boundary conditions in your program’s logic. 3. If you are like most programmers, then you probably are used to returning an error code when a method fails. 4. When you are programming in Java, you should break this habit. When a method can fail, have it throw an exception. 5. This is a cleaner way to handle failure modes. 6. One last point: Java’s Exception – handling statements should not be considered a general mechanism for nonlocal branching. 7. If you do so, it will only confuse your code and make it hard to maintain. 54 THE CHARACTER STREAMS 55 The character Streams 1. While the byte stream classes provide sufficient functionality to handle any type of I/O operation, they cannot work directly with Unicode characters. 2. Since one of the main purposes of Java is to support the “write once, run anywhere” philosophy, it was necessary to include direct I/O support for characters. 3. At the top of the character stream hierarchies are the Reader and Writer abstract classes. Reader Reader is an abstract class that defines java’s model of streaming character input. All of the methods in this class will throw an IOException on error conditions. Writer Writer is an abstract class that defines streaming character output . All of the methods in this class return a void value and throw an IOException in the case of errors. 56 The Methods Defined by Reader Method abstract void close() Description Closes the input source. Further read attempts will generate an IOException. void mark(int numChars) Places a mark at the current point in the input stream that will remain valid until numChars characters are read boolean markSupported() Returns true if mark() / reset() are supported on this stream int read() Returns an integer representation of the next available character from the invoking input stream. -1 is returned when the end of the file is encountered. int read(char buffer[]) Attempts to read up to buffer.length characters into buffer and returns the actual number of character that were successfully read. -1 is returned when the end of the file encountered. abstract int read( char buffer[], int offset, int numChars) Attempts to read up to numChars characters into buffer starting at buffer[offset], returning the number of characters successfully read. -1 is returned when the end of the file is encountered. 57 Method Description boolean ready() Returns true if the next input request will not wait. Otherwise, it returns false. void reset() Resets the input pointer to the previously set mark long skip( long numChars) Skips over numChars characters of input , returning the number of characters actually skipped. 58 The Methods Defined by Writer Method Description abstract void close() Closes the output stream. Further write attempts will generate an IOException. abstract void flush() Finalizes the output state so that any buffers are cleared. That is, it flushes the output buffers. void write (int ch) Writes a single character to the invoking output stream. Note that the parameter is an int, which allows you to call write with expressions without having to cast them back to char. void write(char buffer[]) Writes a complete array of characters to the invoking output stream. abstract void write( char buffer[], int numChars) Writes a subrange of numChars characters from the array buffer, beginning at buffer[offset] to the invoking output stream. void write(String str) Writes str to the invoking output stream. void write(String str, int offset, int numChars) Writes a subrange of numChars characters from the array str, beginning at the specified offset. 59 FileReader The FileReader class creates a Reader that you can use to read the contents of a file. Its most commonly used constructors are shown here: FileReader (String filePath) FileReader (File filObj) Note: Either can throw a FileNotFoundException. Here, filePath is the full path name of a file and fileobj is a File object that describes the file. 60 import java.io.*; class FileReaderDemo { public static void main(String args[]) throws IOException { FileReader fr = new FileReader("FileReaderDemo.java"); BufferedReader br = new BufferedReader(fr); String s; while((s = br.readLine()) != null) { System.out.println(s); } fr.close(); } } 61 FileWriter The FileWriter class creates a Writer that you can use to writet to a file. Its most commonly used constructors are shown here: FileWriter(String filePath) FileWriter(String filePath, boolean append) FileWriter(File fileObj) FileWriter(File fileObj, boolean append) They can throw an IOException. Here, filePath is the full path name of a file, and fileObj is a File Object that describes the file. If append is true, then output is appended to the end fo the file. 62 import java.io.*; class FileWriterDemo { public static void main(String args[]) { try { // Create file FileWriter fstream = new FileWriter("out.txt"); BufferedWriter out = new BufferedWriter(fstream); out.write("Hello Java"); //Close the output stream out.close(); } catch (Exception e) { //Catch exception if any System.err.println("Error: " + e.getMessage()); } } } 63 CharArrayReader CharArrayReader is an implementation of an input stram that uses a character array as the source. The class has two constructos, each of which requires a character array to provide the data source: CharArrayReader(char arrray[]) CharArrayReader(char array[],int start,int numChars) Here, array is the input source. The second constructor creates a Reader from a subset of your character array that begins with the character at the index specified by start and is numChars long. 64 import java.io.*; class CharArrayReaderDemo { public static void main(String args[]) throws IOException { String tmp = "abcdefghijklmnopqrstuvwxyz"; int length = tmp.length(); char c[] = new char[length]; tmp.getChars(0, length, c, 0); CharArrayReader input1 = new CharArrayReader(c); CharArrayReader input2 = new CharArrayReader(c, 0, 5); int i; System.out.println("input1 is:"); while((i = input1.read()) != -1) { System.out.print((char)i); } System.out.println(); System.out.println("input2 is:"); while((i = input2.read()) != -1) { System.out.print((char)i); } System.out.println(); } } 65 CharArrayWriter CharArrayWriter is an implementation of an output stram that uses a character array as the destination. The class has two constructos, each of which requires a character array to provide the data destination: CharArrayWriter() CharArrayWriter(int numChars) In the first form, a buffer with a default size is created. In the second, a buffer is created with a size equal to that specified by numChars. The buffer is held in the buf field of CharArrayWriter. The buffer size will be increased automatically, if needed. The number of characters held by the buffer is contained in the count field of CharArrayWriter. Both buf and count are protected fields. 66 import java.io.*; class CharArrayWriterDemo { public static void main(String args[]) throws IOException { CharArrayWriter f = new CharArrayWriter(); String s = "This should end up in the array"; char buf[] = new char[s.length()]; s.getChars(0, s.length(), buf, 0); f.write(buf); System.out.println("Buffer as a string"); System.out.println(f.toString()); System.out.println("Into array"); char c[] = f.toCharArray(); for (int i=0; i<c.length; i++) { System.out.print(c[i]); } System.out.println("\nTo a FileWriter()"); FileWriter f2 = new FileWriter("test.txt"); f.writeTo(f2); f2.close(); System.out.println("Doing a reset"); f.reset(); for (int i=0; i<3; i++) f.write('X'); System.out.println(f.toString()); }} 67 BufferedReader BufferedReader improves performance by buffering input. It has two constructors: BufferedReader(Reader inputStream) BufferedReader(Reader inputStream,int bufsize) The first form creates a buffered character stream using a default buffer size. In the second, the size of the buffer is passed in bufsize. 68 import java.io.*; class BufferedReaderDemo { public static void main(String args[]) throws IOException { String s = "This is a © copyright symbol " + "but this is © not.\n"; char buf[] = new char[s.length()]; s.getChars(0, s.length(), buf, 0); CharArrayReader in = new CharArrayReader(buf); BufferedReader f = new BufferedReader(in); int c; while((c = f.read()) != -1) { System.out.print((char)c); } } } 69 BufferedWriter A BufferedWriter is a Writer that adds a flush() method that can be used to ensure that data buffers are physically wirtten to the actual output stream. Using a BufferedWriter can increase performance by reducing the number of times data is actually physically written to the output stream. A BufferedWriter has these two constructors: BufferedWriter(Writer outputStream) BufferedWriter(Writer outputStream,int bufsize) The first form creates a buffered character stream using a default buffer size. In the second, the size of the buffer is passed in bufsize. 70 import java.io.*; class BufferedWriterDemo { public static void main(String args[]) throws Exception { // Create a new instance of a BufferedWriter object using a StringWriter. StringWriter sw = new StringWriter(); BufferedWriter bw = new BufferedWriter(sw); // Write to the underlying StringWriter. String str = new String("This is the string being written."); // Print out the 6 characters. bw.write(str, 12, 6); bw.flush(); System.out.println(sw.getBuffer()); // Close the BufferedWriter object and the underlying StringWriter object. sw.close(); bw.close(); } } 71 PushbackReader The PushbackReader class allows one or more characters to be returned to the input stream. This allows you to look ahead in the input stream. Here are its two constructors: PushbackReader(Reader inputStream) PushbackReader(Reader inputStream,int bufSize) The first form creates a buffered stream that allows one character to be pushed back. In the second, the size of the pushback buffer is passed in bufSize. PushbackReader provides unread(), which returns one or more characters to the invoking input stream. It has the three forms shown here: void unread(int ch) void unread(char buffer[]) void unread(char buffer[], int offset, int numChars) The first form pushes back the character passed in ch. This will be the next character returned by a subsequent call to read(). The second form returns the characters in buffer. The third form 72 be pushes back numChars characters beginning at offset from buffer. An IOException will thrown if there is an attempt to return a character when the pushback buffer is full. import java.io.*; class PushbackReaderDemo { public static void main(String args[]) throws IOException { String s = "if (a == 4) a = 0 ; \\n"; char buf[] = new char[s.length()]; s.getChars(0, s.length(), buf, 0); CharArrayReader in = new CharArrayReader(buf); PushbackReader f = new PushbackReader(in); int c; while ((c = f.read()) != -1) { switch(c) { case '=': if ((c = f.read()) == '=') System.out.print(".eq."); else { System.out.print("<-"); f.unread(c); } break; default: System.out.print((char) c); break; } } } } 73 PrintWriter PrintWriter is essentially a character – oriented version of PrintStream. It provides the formatted output methods print() and println(). PrintWriter has four constructors: PrintWriter(OutputStream outputStream) PrintWriter(OutputStream outputStream, boolean flushOnNewline) PrintWriter(Writer outputStream) PrintWriter(Writer outputStream, boolean flushOnNewline) Where flushOnNewline controls whether Java flushes the output stream every time println() is called. If flushOnNewline is true, flushing automatically takes place. If false, flushing is not automatic. The first and third constructors do not automatically flush. 74 import java.io.*; class PrintWriterDemo { public static void main(String args[]) { PrintWriter pw = new PrintWriter(System.out, true); pw.println("This is a string"); int i = -7; pw.println(i); double d = 4.5e-7; pw.println(d); } } 75 SERIALIZATION 76 Serialization 1. Serialization is the process of writing the state of an object to a byte stream. 2. This is useful when you want to save the state of your program to a persistent storage area, such as a file. 3. At a later time, you may restore these objects by using the process of deserialization. 4. Serialization is also needed to implement Remote Method Invocation (RMI). 5. RMI allows a Java object on one machine to invoke a method of a Java object on a different machine. 6. An object may be supplied as an argument to that remote method. 7. The sending machine serializes the object and transmits it. 8. The receiving machine deserializes it. 77 Serializable 1. Only an object that implements the Serializable interface can be saved and restored by the serialization facilities. 2. The Serializable interface defines no members. It is simply used to indicate that a class may be serialized. 3. If a class is serializable, all of its subclasses are also serializable. 4. Variables that are declared as transient are not saved by the serialization facilities. 5. Also static variable are not saved. Externalizable 1. The Java facilities for serialization and deserialization have been designed so that much of the work to save and restore the state of an object occurs automatically. 2. However, there are cases in which the programmer may need to have control over these processes. 3. For example, it may be desirable to use compression or encryption techniques. The Externalizable interface is designed for these situations. 4. The Externalizable interface defines these two methods: void readExternal(ObjectInput inStream) throws IOException, ClassNotFoundException void writeExternal(ObjectOutput outStream) throws IOException 78 In these methods, inStream is the byte stream from which the object is to be read, and outStream is the byte stream to which the object is to be written. ObjectOutput The ObjectOutput interface extends the DataOutput interface and support object Serialization. The following Methods is called the serialize an object. All of these methods will throw an IOException on error condition. Method Description void close() Closes the invoking stream. Further write attempts will generate an IOException. void flush() Finalizes the output state so that any buffers are cleared. That is, it flushes the output buffers. void wirte(byte buffer[]) Writes an array of bytes to the invoking stream. void write(byte buffer[], int offset, int numBytes) Writes a subrange of numBytes bytes from the array buffer, beginning at buffer[offset]. void write(int b) Writes a single byte to the invoking stream. The byte written is the low – order byte of b. Void writeObject(Object obj) Writes object obj to the invoking stream. 79 ObjectOutputStream The ObjectOutputStream class extends the OutputStream class and implements the ObjectOutput interface. It is responsible for writing objects to a stream. A constructor of this class is: ObjectOutputStream(OutputStream outStream) throws IOException The argument outStream is the output stream to which serialized objects will be written. Method Description void close() Closes the invoking stream. Further write attempts will generate an IOException. void flush() Finalizes the output state so that any buffers are cleared. That is, it flushes the output buffers. void wirte(byte buffer[]) Writes an array of bytes to the invoking stream. void write(byte buffer[], int offset, int numBytes) Writes a subrange of numBytes bytes from the array buffer, beginning at buffer[offset]. void write(int b) Writes a single byte to the invoking stream. The byte written is the low – order byte of b. void writeBoolean(boolean b) Writes boolean to the invoking stream. 80 Method Description void writeByte(int b) Writes a byte to the invoking stream. The byte written is the low – order byte of b. void writeBytes(String str) Writes the bytes representing str to the invoking stream. void writeChar(int c) Writes a char to the invoking stream. void writeChars(String str) Writes the characters in str to the invoking stream. void writeDouble(double d) Writes a double to the invoking stream. void writeFloat(float f) Writes a float to the invoking stream. void writeInt(int i) Writes a int to the invoking stream. void WriteShort(int i) Writes a short to the invoking stream. void writeLong(long i) Writes a long to the invoking stream. final void writeObject(Object obj) Writes a obj to the invoking stream. 81 ObjectInput The ObjectInput interface extends the DataInput interface and support object Serialization. The following Methods is called the serialize an object. All of these methods will throw an IOException on error condition. Method Description int available() Returns the number of bytes that are now available in the input buffer. void close() Closes the invoking stream. Further read attempts will generate an IOException. int read() Returns an integer representation of the next available byte of input. -1 is returned when the end of the file is encountered. int read(byte buffer[]) Attempts to read up to buffer length bytes into buffer, returning the number of bytes that were successfully read. -1 is returned when the end of the file is encountered. int read(byte buffer[], int offset, int numBytes) Attempts to read up to numBytes bytes into buffer starting at buffer[offset], returning the number of bytes that were successfully read. -1 is returned when the end of the file is encountered. 82 Method Description Object readObject() Reads an object from the invoking stream. Long skip(long numBytes) Ignores(that is, skips) numBytes bytes in the invoking stream, returnign the number of bytes actually ignored. ObjectInputStream The ObjectInputStream class extends the InputStream class and implements the ObjectInput interface. It is responsible for Reading objects from a stream. A constructor of this class is: ObjectInputStream(InputStream inStream) throws IOException, StreamCorruptedException The argument inStream is the input stream from which serialized objects should be read. 83 Method Description int available() Returns the number of bytes that are now available in the input buffer. void close() Closes the invoking stream. Further read attempts will generate an IOException int read() Returns an integer representation of the next available byte of input. -1 is returned when the end of the file is encountered. int read(byte buffer[],int offset,int numBytes) Attempts to read up to numBytes bytes into buffer starting at buffer[offset], returning the number of bytes successfully read. -1 is returned when the end of the file is encountered. boolean readBoolena() Reads and returns boolean from the invoking stream. byte readByte() Reads and returns a byte from the invoking stream. char readChar() Reads and returns a char from the invoking stream. double readDouble() Reads and returns a double from the invoking stream. float readFloat() Reads and returns a float from the invoking stream. void readFully(byte buffer[]) Reads buffer length bytes into buffer. Returns only when all bytes have been read. void readFully(byte buffer[], int offset, int numBytes) 84 Reads numBytes bytes into buffer starting at buffer[offset]. Returns only when numBytes have been read. Method Description int readInt() Reads and returns an int from the invoking stream. long readLong() Reads and returns a long from the invoking stream. final Object readObject() Reads and returns an object from the invoking stream. short readShort() Reads and returns a short from the invoking stream. int readUnsignedByte() Reads and returns an unsigned byte from the invoking stream. int readUnsignedShort() Reads an unsigned short from the invoking stream. 85 import java.io.*; class SerializationDemo { public static void main(String arg[]) { //Object Serialization try { MyClass object1 = new MyClass("Hello", -7,2.7e10); System.out.println("Object1: " + object1); FileOutputStream fos = new FileOutputStream("serial"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(object1); oos.flush(); oos.close(); } catch(Exception e) { System.out.println("Exception during serialization: " + e); System.exit(0); 86 } //Object Deserialization try { MyClass object2; FileInputStream fis = new FileInputStream("serial"); ObjectInputStream ois = new ObjectInputStream(fis); object2 = (MyClass)ois.readObject(); ois.close(); System.out.println("object2: " + object2); } catch(Exception e) { System.out.println("Exception during deserialization: " + e); System.exit(0); } } } class MyClass implements Serializable { String s; int i; double d; public MyClass(String s,int i,double d) { this.s = s; this.i = i; this.d = d; } public String toString() { return "S=" + s + "; i=" + i + "; d=" + d; } } 87 Converting Primitive Numbers to Object Numbers using Constructor Methods Constructor Calling Conversion Action Integer intval = new Integer(i) Primitive integer to Integer object Float floatval = new Float(f) Primitive float to Float object Double doubleval = new Double(d) Primitive double to Double object Long longval = new Long(l) Primitive long to Long object Converting Object Numbers to Primitive Numbers using typeValue() method Method Calling Conversion Action int i = IntVal.intValue() Object to Primitive integer float f = FloatVal.floatValue() Object to Primitive float long l = LongVal.longValue() Object to Primitive long double d = DoubleVal.doubleValue() Object to Primitive double 88 Converting Numbers to Strings Using a String( ) Method Constructor Calling Conversion Action str = Integer.toString(i) Primitive Integer to string str = Float.toString(f) Primitive float to string str = Double.toString(d) Primitive double to string str = Long.toString(l) Primitive long to string Converting String Objects to Numeric Object Using the Static Method ValueOf() Method Calling Conversion Action DoubleVal = Double.ValueOf(str) Converts String to Double object FloatVal = Float.ValueOf(str) Converts String to Float object IntVal = Integer.ValueOf(str) Converts string to Integer object LongVal = Long.Valueof(str) Converts string to Long object 89 Converting Numberic Strings to Primitive Numbers Using Parsing Methods Constructor Calling Conversion Action int i = Integer.parseInt(str) Converts String to Primitive Integer long l = Long.parseLong(str) Converts String to Primitive long 90 THREAD MODEL 91 INTRODUCTION 1. Those who are familiar with the modern operation systems such as windows 95 may recognize that they can execute several programs simultaneously. This ability is known as multitasking. In System’s terminology, it is called multithreading. 2. Multithreading is a conceptual programming paradigm where a program is divided into two or more subprograms, which can be implemented at the same time in parallel. For example, one subprogram can display an animation on the screen while another may build the next animation to be displayed. This something similar to dividing a task into subtasks and assigning them to different people for execution independently and simultaneously. 3. In most of our computers, we have only a single processor and therefore, in reality, the processor is doing only one thing at a time. However, the processor switches between the processes so fast that it appears to human beings that all of them are being done simultaneously. 4. Java programs contain only a single sequential flow of control. This is what happens when we execute a normal program. The program begins, runs through a sequence of executions, and finally ends. At any given point of time, there is only one statement under execution. 5. A thread is similar to a program that has a single flow of control. It has a beginning, a body and an end, and executes commands sequentially. In fact, all main programs in our earlier examples can be called single – threaded programs. 6. A unique property of Java is its support for multithreading. That is, java enables us to use multiple flows of control in developing programs. Each flow of control may be thought of as in separate tiny program known as thread that runs in parallel to others. 92 SINGLE THREADED PROGRAM class ABC { --------------------------------------------------------------------------------------------------------------} Beginning Single – threaded body of execution End 93 MULTITHREADED PROGRAM Main Thread _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ start _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ Thread A switching start _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ Thread B Main method module start switching _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ 94 Thread C 7. A program that contains multiple flows of control is known as multithreaded program. 8. The above fig. is a java program with four threads, one main and three others. The main thread is actually the main method module, which is designed to create and start the other three threads, namely A, B and C 9. Once initiated by the main thread, the threads A, B and C run concurrently and share the resources jointly. The ability of a language to support multithreads is referred to as concurrency. 10. Threads in java are subprograms of main application program and share the same memory space, they are known as lightweight threads or lightweight processes.. Note: It is important to remember that ‘threads running in parallel’ does not really mean that they actually run at the same time. Since all the threads are running on a single processor, the flow of execution is shared between the threads. 95 CREATING THREADS 1. Creating threads in Java is simple. 2. Threads are implemented in the form of objects that contain a method called run(). 3. The run() method is the heart and soul of any thread. It makes up the entire body of a thread and is the only method in which the thread’s behaviour can be implemented. 4. A typical run() would appear as follows: public void run() { ---------------------------------------------------} Statements for implementing thread 96 5. The run() method should be invoked by an object for the concerned thread. 6. This can be achieved by creating the thread and initiating it with the help of another thread method called start(). 7. A new thread can be created in two ways. a. By creating a thread class: Define a class that extends Thread class and override its run() method with the code required by the thread. b. By converting a class to a thread: Define a class that implements Runnable interface. The Runnable interface has only one method, run(), that is to be defined in the method with the code to be executed by the thread. 97 EXTENDING THE THREAD CLASS We can make our class runnable as a thread by extending the class java.lang.Thread. This gives us access to all the thread methods directly. It includes the following steps: 1. Declare the class as extending the Thread class 2. Implement the run() method that is responsible for executing the sequence of code that the thread will execute. 3. Create a thread object and call the start() method to initiate the thread execution. 1. Declaring the class class MyThread extends Thread { --------------------------------------------------------} 98 2. Implementing the run() Method public void run() { ----------------------------------------------------------------} Thread Code Here 3. Starting New Thread MyThread aThread = new MyThread(); aThread.start(); //Invoke run() method 99 Creating threads using the thread class class A extends Thread { public void run() { for(int i = 1;i <= 5;i++) { System.out.println("\tFrom Thread A : i = " + i); } System.out.println("Exit from A "); } } class B extends Thread { public void run() { for(int j = 1;j <= 5;j++) { System.out.println("\tFrom Thread B : j = " + j); } System.out.println("Exit from B "); } } 100 class C extends Thread { public void run() { for(int k = 1;k <= 5;k++) { System.out.println("\tFrom Thread C : k = " + k); } System.out.println("Exit from C "); } } class ThreadTest { public static void main(String args[]) { A a = new A(); B b = new B(); C c = new C(); a.start(); b.start(); c.start(); } } 101 IMPLEMENTING THE ‘RUNNABLE’ INTERFACE The Runnable interface declares the run() method that is required for implementing threads in our programs. To do this, we must perform the steps listed below: 1. Declare the class an implementing the Runnable interface. 2. Implementing the run() method. 3. Create a thread by defining an object that is instanitiated form the “runnable” class as the target of the thread. 4. Call the thread’s start() method to run the thread. 102 import java.lang.Thread; class X implements Runnable { public void run() { for(int i = 1;i <= 5;i++) { System.out.println("\tFrom Thread A : i = " + i); } System.out.println("Exit from A "); } } class Y implements Runnable { public void run() { for(int j = 1;j <= 5;j++) { System.out.println("\tFrom Thread B : j = " + j); } System.out.println("Exit from B "); } } 103 class Z implements Runnable { public void run() { for(int k = 1;k <= 5;k++) { System.out.println("\tFrom Thread C : k = " + k); } System.out.println("Exit from C "); } } class RunnableTest { public static void main(String args[]) { X runnableX = new X(); Thread threadX = new Thread(runnableX); Y runnableY = new Y(); Thread threadY = new Thread(runnableY); Z runnableZ = new Z(); Thread threadZ = new Thread(runnableZ); threadX.start(); threadY.start(); threadZ.start(); } } 104 LIFE CYCLE OF A THREAD During the life time of a thread, there are many states it can enter. They include 1. Newborn state 2. Runnable state 3. Running state 4. Blocked state 5. Dead state 105 State Transition diagram of a Thread New Thread Newborn start stop Active Thread Runnable Running stop Dead yield suspend resume sleep stop notify wait Idle Thread Killed Thread Blocked (Not Runnable) 106 Newborn State When we create a thread object, the thread is born and is said to be in newborn state. The thread is not yet scheduled for running. At this state, we can do only one of the following things with it: 1. schedule it for funning using start() method. 2. kill it using stop() method. Newborn start Runnable state stop Dead State 107 Runnable State 1. The runnable state means that the thread is ready for execution and is waiting for the availability of processor. 2. That is, the thread has joined the queue of threads that are waiting for execution. 3. If all threads have equal priority, then they are given time slots for execution in round robin fashion. i.e., first – come, first – serve manner. 4. The thread that relinquishes contol joins the queue at the end and again waits for its turn. This process of assigning time to threads is known as time – slicing. 5. However, if we want a thread to relinquish control to another thread of equal priority before its turn comes, we can do so by using the yield() method. Yield() Running Thread 108 Running State Running means that the processor has given its time to the thread for its execution. The thread runs until it relinquishes control on its own or it is preempted by a higher priority thread. A running thread may relinquish its control in one of the following situations: 1. suspend() and resume() It has been suspended using suspend() method. A suspended thread can be revived by using the resume() method. This approach is useful when we want to suspend a thread for some time due to certain reason, bur do not want to kill it suspend() resume() Running Runnable Suspended 109 2. sleep() It has been made to sleep, We can put a thread to sleep for a specified time period using the method sleep (time) where time is in milliseconds. This means that the thread is out of the queue during this time period. The thread re – enters the runnable state as soon as this time period is elapsed. sleep (t) after t Running Runnable Sleeping 110 3. wait() and notify() It has been told to wait until some event occurs. This is done using the wait() method. The thread can be scheduled to run again using the notify() method. wait() notify () Running Runnable Waiting Blocked State 1. A thread is said to be blocked when it is prevented from entering into the runnable state and subsequently the running state. 2. This happens when the thread is suspended, sleeping, or waiting in order to satisfy certain requirements. 3. A blocked thread is considered “not runnable” but not dead therefore fully qualified to run again. 111 Dead State 1. Every thread has life cycle. A running thread ends its life when it has completed executing its run() method. 2. It is a natural death. However, we can kill it by sending the stop message to it at any state thus causing a premature death to it. 3. A thread can be killed as soon it is born, or while it is running, or even when it is in “not runnable” (blocked) condition. 112 import java.lang.Thread; class A extends Thread { public void run() { for(int i = 1;i <= 5;i++) { if(i == 1) yield(); System.out.println("\tFrom Thread A : i = " + i); } System.out.println("Exit from A "); } } class B extends Thread { public void run() { for(int j = 1;j <= 5;j++) { System.out.println("\tFrom Thread B : j = " + j); if(j==3) stop(); } System.out.println("Exit from B "); } } 113 class C extends Thread { public void run() { for(int k = 1;k <= 5;k++) { System.out.println("\tFrom Thread C : k = " + k); if(k==1) try { sleep(1000); } catch(Exception e) { } } System.out.println("Exit from C "); } } class ThreadTest_1 { public static void main(String args[]) { A a = new A(); B b = new B(); C c = new C(); System.out.println("Start Thread A"); a.start(); System.out.println("Start Thread B"); b.start(); System.out.println("Start Thread C"); c.start(); System.out.println("End of main Thread"); } } 114 Using isAlive() and join() isAlive() Two ways exist to determine whether a thread has finished. First, you can call isAlive() on the thread. The method is defined by Thread, and its general form is shown here: final boolean isAlive() The isAlive() method returns true if the thread upon which it is called is still running. It returns false otherwise. join While isAlive() is occasinally useful, the method that you will more commonly use to wait for a thread to finish is called join(), shown here: final void join() throws InterruptedException This method waits until the thread on which it is called terminates. Its name comes from the concept of the calling thread waiting until the specified thread 115 joins it. class A extends Thread { public void run() { for(int i = 1;i <= 5;i++) { System.out.println("\tFrom Thread A : i = " + i); } System.out.println("Exit from A "); } } class B extends Thread { public void run() { for(int j = 1;j <= 5;j++) { System.out.println("\tFrom Thread B : j = " + j); } System.out.println("Exit from B "); } } 116 class C extends Thread { public void run() { for(int k = 1;k <= 5;k++) { System.out.println("\tFrom Thread C : k = " + k); } System.out.println("Exit from C "); } } class ThreadTest { public static void main(String args[]) { A a = new A(); B b = new B(); C c = new C(); 117 System.out.println("Start Thread A"); a.start(); System.out.println("Start Thread B"); b.start(); System.out.println("Start Thread C"); c.start(); System.out.println("End of main Thread"); System.out.println("Thread One is Alive: " + a.isAlive()); System.out.println("Thread two is Alive: " + b.isAlive()); System.out.println("Thread three is Alive: " + c.isAlive()); try { a.join(); b.join(); c.join(); } catch(InterruptedException e) { System.out.println("Main Thread Interrupted"); } System.out.println("Thread One is Alive: " + a.isAlive()); System.out.println("Thread two is Alive: " + b.isAlive()); System.out.println("Thread three is Alive: " + c.isAlive()); } } 118 THREAD PRIORITY 1. In java, each thread is assigned a prioriy, which affects the order in which it is scheduled for running. 2. The threads of the same priority are given equal treatment by the Java scheduler and, therefore, they share the processor of a first – come, first – serve basis. ThreadName.setPriority(intNumber); The intNumber is an integer value to which the thread’s priority is set. The Thread class defines several priority constants: MIN_PRIORITY = 1 NORM_PRIORITY = 5 MAX_PRIORITY = 10 The intNumber may assume one of these constants or any value between 1 and 10. Note that the default setting is NORM_PRIORITY 119 import java.lang.Thread; class A extends Thread { public void run() { for(int i = 1;i <= 5;i++) { System.out.println("\tFrom Thread A : i = " + i); } System.out.println("Exit from A "); } } class B extends Thread { public void run() { for(int j = 1;j <= 5;j++) { System.out.println("\tFrom Thread B : j = " + j); } System.out.println("Exit from B "); } } 120 class C extends Thread { public void run() { for(int k = 1;k <= 5;k++) { System.out.println("\tFrom Thread C : k = " + k); } System.out.println("Exit from C "); } } class ThreadPriority { public static void main(String args[]) { A a = new A(); B b = new B(); C c = new C(); c.setPriority(5); b.setPriority(10); a.setPriority(1); //c.setPriority(NORM_PRIORITY); //b.setPriority(MAX_PRIORITY); //a.setPriority(MIN_PRIORITY); a.start(); b.start(); c.start(); } } 121