-
Notifications
You must be signed in to change notification settings - Fork 3
Chapter 4 : Exception Handling and Multithreading
- Errors are the abnormal situations arise at Compile Time. An error may produce following problems:
- Incorrect output
- Abrupt termination of the program
- System crash
- Therefore it is important to detect and manage all the possible error conditions in the program.
- Exceptions are the abnormal situations arise at Run Time.
Types of Errors:
- Compile Time Errors
- Run Time Errors (Exceptions)
Compile Time Errors:
- All syntax errors will be detected and displayed by the Java Compiler and therefore these errors known as Compile Time Errors.
- Whenever the compiler displays an error, it will not create .class file. It is therefore necessary to fix all errors before we can successfully Compile and Run the program.
- Most of the Compile Time Errors are due to typing mistakes. Typological errors are hard to find. We may have to check the code word by word or even character by character.
// Compile time error
class Sample
{
public static void main (String args [ ])
{
System.out.println(“Hello Java”) // Missing ;
}
}
// Output: While compiling above program, compiler displays following error:
// Sample.java : 6: ‘; ‘ expected
// System.out.println (“Hello Java”);
// ^
// 1 error
Common Compile Time Errors:
- Missing semicolons.
- Missing (or mismatch of) brackets in classes and methods.
- Misspelling of identifiers and keywords.
- Missing double quotes in Strings.
- Use of undeclared variables.
- Incompatible types in assignments / initializations.
- Bad reference to objects.
- Use of = in place of == operator.
- Due to incorrect directory path, and so on.
Run Time Errors (Exceptions):
- Sometimes, program may compile successfully creating the .class file but may not run properly. In such cases Java generates an error message and aborts the program. This is due to exceptions.
- An exception may produce following problems:
- Incorrect output
- Abrupt termination of the program
- System crash
- Therefore it is important to detect and manage all the possible exception conditions in the program.
- Exceptions are the abnormal situations arise at Run Time.
// Example of Run Time Error:
class ExceptionDemo
{
public static void main (String args [ ])
{
int a=10, b=5, c=5;
int x,y;
x = a / (b-c); // Division by zero
System.out.println(“Result x = ”+x);
y = a / (b+c);
System.out.println(“Result y = ”+y);
}
}
// Output: Above program is syntactically correct and therefore does get compile. But while running it displays following message and stop without // running further statements:
// java.lang.ArithmeticException: / by zero
// at ExceptionDemo.main (ExceptionDemo.java:7)
Common Run Time Exceptions:
- Dividing an integer by zero.
- Accessing an element that is out of bounds of an array.
- Accessing a character that is out of bounds of a String.
- Trying to store a value into an array of an incompatible class or type.
- Trying to use negative size for an array.
- Trying to illegally change state of a thread.
- Trying to cast an instance of a class to one of its subclass.
- Converting invalid string to a number.
- Passing a parameter that is not in a valid range or value for a method.
- Using a null object reference as a legitimate object reference to access method or a variable.
- Exception is a run-time error in the program.
- Exception can be generated by the Java run time system or by manually by the code. Exceptions generated by the Java are related to the fundamental errors that violate the java constraints.
- When the Java interpreter encounters an exception such as dividing an integer by zero, it creates an exception object and throws it to inform that an exception has occurred.
- If the exception object is not caught and handled properly, the interpreter will generate an error message and terminate the program.
- In order to start the execution of remaining program, we should try to catch the exception object thrown by the error condition and then display appropriate message for taking corrective actions.
- This task is known as exception handling.
- The purpose of exception handling mechanism is to provide a means to detect and report an “exceptional circumstances” so that appropriate action can be taken.
- Exception Handling Contains Following Tasks:
- Find the problem (Hit the exception).
- Inform that an error has occurred (Throw the exception).
- Receive the error information (Catch the exception).
- Take corrective actions (Handle the exception).
- Exception Handling Contains Two Parts:
- To detect and to throw exception.
- To catch and handle exception.
Syntax of Exception Handling Code:
- Java exception handling is managed by following five keywords:
- try:
- The program statements that to be monitored for exceptions are contained within try block.
- If an exception occurs within try block, it is thrown.
- try block can have one or more statements that could generate an exception.
- If anyone statement generates an exception, the remaining statements in the block are skipped and execution jumps to the catch block that is placed next to try block.
- catch:
- catch block catches the exception thrown by the try block and handle it appropriately.
- catch block added immediately after the try block.
- try block must be followed by at least one catch block.
- catch statement is passed a single parameter. If the catch parameter matches with the type of exception object thrown, then catch block will be executed. Otherwise exception is not caught and the default exception handler will cause execution to terminate.
- throw:
- System generated exceptions are thrown automatically by Java run-time system.
- To manually throw an exception throw keyword is used.
- General from of throw is: throw ThrowableInstance
- throws:
- Any exception that is generated out of a method must be specified by a throws clause.
- It just throws exception and calling method will handle it.
- If a method can cause an exception that it does not handle, then it must specify it by keyword throws, so that caller of the method can guard themselves against that exception.
- finally:
- Any code that must be executed before a method returns is put in a finally block.
- It executes after a try/catch block has completed.
- The finally block will execute whether or not an exception is thrown.
- We can use it to perform certain house-keeping operations such as closing files and releasing system resources.
- The finally clause is optional. However, each try statement requires at least one catch or a finally clause.
// Syntax:
try
{
statements; // generates an exception
}
catch (Exception-type1 e)
{
statements; // process the exception-type1
}
catch (Exception-type2 e)
{
statements; // process the exception-type2
}
catch (Exception-typeN e)
{
statements; // process the exception-typeN
}
finally
{
statements; // block of code to be executed before try block ends
}
Java Built-In Exceptions:
- There are two types of exceptions or Runtime Exceptions:
- Unchecked Runtime Exception
- ArithmeticException :- Arithmetic error, such as divide by zero.
- ArrayIndexOutOfBoundsException :- Array index is out of bounds.
- ArrayStoreException :- Assignment to an array element of incompatible data type.
- ClassCastException :- Invalid Cast.
- IllegalArgumentException :- Illegal argument used to invoke a method.
- IllegalMonitorStateException :- Illegal monitor operation, such as waiting on an unlocked thread.
- IllegalStateException :- Environment or application is in incorrect state.
- IllegalThreadStateException :- Requested operation not compatible with current thread state.
- IndexOutOfBoundsException :- Some type of index is out of bounds.
- NegativeArraySizeException :- Array created with negative size.
- NullPointerException :- Invalid use of null reference.
- NumberFormatException :- Invalid conversion of string to a numeric format.
- SecurityException :- Attempt to violate security.
- StringIndexOutOfBounds :- Attempt to index outside the bound of the string.
- UnsupportedOperationException :- Unsupported operation was encountered.
- Checked Runtime Exception
- ClassNotFoundException :- Class not found.
- CloneNotSupportedException :- Attempt to clone an object that does not implement the
Clonable
interface. - IllegalAccessException :- Access to the class 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.
Multiple Catch Statement:
- It is possible to have more than one catch statement in the catch block as illustrated below.
try
{
statements; // generates an exception
}
catch (Exception-type1 e)
{
statements; // process the exception-type1
}
catch (Exception-type2 e)
{
statements; // process the exception-type2
}
|
catch (Exception-typeN e)
{
statements; // process the exception-typeN
}
- When an exception in try block is generated, the Java treats the multiple catch statements like case in a switch statement. The first statement whose parameter matches with the exception object will be executed, and the remaining statements will skipped.
- We can have simply a catch statement with an empty block.
- Example: catch (Exception e);
- The catch statement simply ends with a semicolon, which does nothing. This statement will catch an exception and then ignore it.
Using Finally Statement:
- Java supports finally statement that can be used to handle an exception that is not caught by any of the previous catch statements. Finally block can be used to handle any exception.
- Any code that must be executed before a method returns is put in a finally block.
- It executes after a try/catch block has completed.
- The finally block will execute whether or not an exception is thrown.
- We can use it to perform certain house-keeping operations such as closing files and releasing system resources.
- The finally clause is optional. However, each try statement requires at least one catch or a finally clause.
Nested try Statements:
- The try statement can be nested; i.e. try statement can be written inside another try block.
- If an inner try statement does not have a catch for a particular exception, then the next try statement’s catch checked for a match. This continues until one of the catch statements match, or until the entire nested try statements are exhausted.
- If no catch statement matches, then the Java run-time system will handle the exception.
// Program of nested try statements.
class NestTry
{
public static void main(String args[])
{
try
{
int a = args.length;
int b = 42 / a;
System.out.println("a = " + a);
try
{
if(a==1)
a = a/(a-a);
if(a==2)
{
int c[] = { 1 };
c[42] = 99;
}
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println("Array index out-of-bounds: " + e);
}
}
catch(ArithmeticException e)
{
System.out.println("Divide by 0: " + e);
}
}
}
// Output: C:\>java NestTry
// Divide by 0: java.lang.ArithmeticException: / by zero
// C:\>java NestTry One
// a = 1
// Divide by 0: java.lang.ArithmeticException: / by zero
// C:\>java NestTry One Two
// a = 2
// Array index out-of-bounds:
// java.lang.ArrayIndexOutOfBoundsException
Program Explanation: If no command-line arguments, a divide-by-zero exception is generated by the outer try block. If one command-line argument, a divide-by-zero exception is generated by the nested try block. Since the inner block does not catch this exception, it is passed on to the outer try block. If two command-line arguments, an array boundary exception is generated from within the inner try block.
- When Java program causes an Exception, then the Exception responds to an exception by throwing another exception. Therefore, the first generated exception causes for throwing another exception in turn. This technique is known as Chained Exception.
- With the help of chained exception it may be easier to know that when one Exception causes another Exception.
- Two constructors of Throwable class supports chained exception are listed below:
- Throwable (Throwable cause): Parameter cause specifies the actual cause of exception.
- Throwable (String str, Throwable cause): String str specifies exception description and cause specifies the actual cause of exception.
- Two methods of Throwable class that supports the chained exception:
- Throwable getCause( ): It returns actual cause of currently generated exception.
- Throwable initCause( ): It sets the fundamental exception with invoking exception.
// Program to demonstrate chained exception.
class ChainDemo
{
public static void main(String args[]) throws Exception
{
int n=20, result=0;
try
{
result = n/0;
System.out.println(“The Result Is “+result);
}
catch(ArithmeticException ae)
{
System.out.println(“Arithmetic Exception occurred: ”+ae);
try
{
throws new NumberFormatException( );
}
catch(NumberFormatException ae)
{
System.out.println(“Chained exception thrown manually: “+ae);
}
}
}
}
// Output: Arithmetic Exception occurred:
// java.lang.ArithmeticException: / by zero
// Chained exception thrown manually:
// java.lang.NumberFormatException
- We can throw our own user defined exception using the keyword throw.
- Syntax: throw new Throwable_SubClass;
-
Examples: throw new ArithmeticException ();
Throw new NumberFormatException ();
- Program: Exception is a subclass of Throwable therefore in following program
- MyException is a subclass of Throwable class. An object of a class that extends Throwable can be thrown and caught.
MyException extends Exception
{
MyException(String msg)
{
super(msg);
}
}
Class TestMyException
{
public static void main(String args[ ])
{
double x = Double.parseDouble(args[0]);
double y = Double.parseDouble(args[1]);
try
{
double z = x / y;
if(z<0.1)
throw new MyException(“Number is too small”);
else
System.out.println(“Result = “ + z);
}
catch(MyException me)
{
System.out.println(me.getMessage());
}
}
}
- Multithreading is a concept where a program (process) is divided into two or more (multiple) subprograms (processes), which can be implemented at the same time in parallel.
- It is a form of multitasking. A program that contains multiple flows of control is called as multithreaded program.
- Multithreading enables to write very efficient programs that makes maximum use of the CPU and kept idle time to a minimum. This is especially important for the interactive, networked environment in which Java operates.
- Each part of program is called as thread. A thread is similar to a program that has a single flow of control.
- The program begins, runs through a sequence of executions, and finally ends. At any point of time, there is only one statement under execution.
- Example: In case of web browser one subprogram can display text, other can display images and some other can display videos and many more from the website.
- 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 processor switches between the processes so fast that it appears to us that all of them being done simultaneously.
Types of Multitasking:
- Process based:
- A process is a program that is executing.
- Process based multitasking is the feature that allows the computer to run two or more programs concurrently.
- For example, process based multitasking enables to run Java compiler at the same time we can use the text editor.
- In process based multitasking program is the smallest unit of code that can be dispatched by the scheduler.
- Process is a heavy weight task that requires their own address space.
- Interprocess communication is expensive and limited.
- Context switching from one process to another is costly.
- Java programs make the use of process based multitasking environment, but the process based multitasking is not under the control of Java.
- Thread based:
- In a thread based multitasking thread is the smallest unit of dispatch able code. That means single program can perform two or more tasks simultaneously.
- For example, a text editor can format text at the same time that is printing, as long as the two separate threads are performing these two actions.
- Thus the process based multitasking deal with big picture, and the thread based multitasking handles the details.
- Multitasking threads require fewer overheads than multitasking processes.
- The threads are light weight.
- They share the same address space.
- Interthread communication is inexpensive.
- Context switching from one thread to other thread is low cost.
- However, the multithreading is multitasking in Java.
- Threads in Java are implemented in the form of objects that contain a method called run ( ). 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 behavior can be implemented.
public void run ( )
{
---------------
--------------- // statements for implementing Thread
---------------
}
- The run( ) method should be called by an object of the concerned Thread. This can be achieved by creating Thread and initiating it with the help of another Thread method start( ).
- Ways of creating Threads:
-
By creating a Thread class (Extending Thread): Define a class that extends Thread class and override its run ( ) method with the code required by the Thread.
-
By converting a class to a Thread (Implementing 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.
-
Extending the Thread class
- We can make our class runnable as thread by extending java.lang.Thread
- This gives us access to all Thread methods directly.
import java.lang.Thread;
class A extends Thread
{
public void run()
{
for(int i=1;i<=5;i++)
{
System.out.println("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("j = "+j);
}
System.out.println("Exit From B");
}
}
class C extends Thread
{
public void run()
{
for(int k=1;k<=5;k++)
{
System.out.println("k = "+k);
}
System.out.println("Exit From c");
}
}
class ThreadDemo
{
public static void main(String args[])
{
new A( ).start( );
new B( ).start( );
new C( ).start( );
}
}
/*
Output: i = 1
i = 2
j = 1
k = 1
i = 3
i = 4
i = 5
j = 2
Exit From A
j = 3
k = 2
k = 3
k = 4
k = 5
Exit From C
j = 4
j = 5
Exit From B
*/
- Implementing the Runnable Interface:
- The Runnable interface declares the run() method that is required for implementing threads in our programs.
class A implements Runnable // Step 1
{
public void run() // Step 2
{
for(int i=1;i<=5;i++)
{
System.out.println("i = "+i);
}
System.out.println("Exit A");
}
}
class B implements Runnable
{
public void run()
{
for(int j=1;j<=5;j++)
{
System.out.println("j = "+j);
}
System.out.println("Exit B");
}
}
class RunDemo
{
public static void main(String args[])
{
A aobj=new A();
B bobj=new B();
Thread t1=new Thread(aobj); // Step 3
t1.start(); // Step 4
Thread t2=new Thread(bobj);
t2.start();
}
}
/*
Output: i = 1
i = 2
j = 1
j = 2
i = 3
i = 4
i = 5
Exit From A
j = 3
j = 4
j = 5
Exit From B
*/