Unit III
Unit III
In Java, Exception is an unwanted or unexpected event, which occurs during the execution of a program, i.e. at run time,
that disrupts the normal flow of the program’s instructions. Exceptions can be caught and handled by the program. When
an exception occurs within a method, it creates an object. This object is called the exception object. It contains information
about the exception, such as the name and description of the exception and the state of the program when the exception
occurred.
Device failure
Code errors
Errors represent irrecoverable conditions such as Java virtual machine (JVM) running out of memory, memory leaks, stack
overflow errors, library incompatibility, infinite recursion, etc. Errors are usually beyond the control of the programmer, and
we should not try to handle errors.
1.Checked Exception
2.Unchecked Exception
3.Error
1) Checked Exception
The classes that directly inherit the Throwable class except RuntimeException and Error are known as checked exceptions.
For example, IOException, SQLException, etc. Checked exceptions are checked at compile-time.
2) Unchecked Exception
The classes that inherit the RuntimeException are known as unchecked exceptions. For example, ArithmeticException,
NullPointerException, ArrayIndexOutOfBoundsException, etc. Unchecked exceptions are not checked at compile-time, but
they are checked at runtime.
3) Error
Error is irrecoverable. Some example of errors are OutOfMemoryError, VirtualMachineError, AssertionError etc.
try The "try" keyword is used to specify a block where we should place an exception code. It means we can't use try
block alone. The try block must be followed by either catch or finally.
catch The "catch" block is used to handle the exception. It must be preceded by try block which means we can't use catch
block alone. It can be followed by finally block later.
finally The "finally" block is used to execute the necessary code of the program. It is executed whether an exception is
handled or not.
throws The "throws" keyword is used to declare exceptions. It specifies that there may occur an exception in the method. It
doesn't throw an exception. It is always used with method signature.
try{
int data=100/0;
}catch(ArithmeticException e)
System.out.println(e);
OUTPUT
Java try block is used to enclose the code that might throw an exception. It must be used within the method.
If an exception occurs at the particular statement in the try block, the rest of the block code will not execute. So, it is
recommended not to keep the code in try block that will not throw an exception.
}catch(Exception_class_Name ref){}
try{
}finally{}
Java catch block is used to handle the Exception by declaring the type of exception within the parameter. The declared
exception must be the parent class exception ( i.e., Exception) or the generated exception type. However, the good
approach is to declare the generated type of exception.
The catch block must be used after the try block only. You can use multiple catch block with a single try block.
But if the application programmer handles the exception, the normal flow of the application is maintained,
i.e., rest of the code is executed.
Example 1
TryCatchExample1.java
Output:
As displayed in the above example, the rest of the code is not executed (in such case, the rest of the code statement is not
printed).
There might be 100 lines of code after the exception. If the exception is not handled, all the code below the exception won't
be executed.
Let's see the solution of the above problem by a java try-catch block.
Example 2
TryCatchExample2.java
try
catch(ArithmeticException e)
{
System.out.println(e);
OUTPUT
java.lang.ArithmeticException: / by zero
As displayed in the above example, the rest of the code is executed, i.e., the rest of the code statement is printed.
A try block can be followed by one or more catch blocks. Each catch block must contain a different exception handler. So, if
At a time only one exception occurs and at a time only one catch block is executed.
All catch blocks must be ordered from most specific to most general, i.e. catch for ArithmeticException must come before
catch for Exception.you have to perform different tasks at the occurrence of different exceptions, use java multi-catch block.
Example 1
MultipleCatchBlock1.java
try{
a[5]=30/0;
catch(ArithmeticException e)
catch(ArrayIndexOutOfBoundsException e)
catch(Exception e)
OUTPUT
Example 2
MultipleCatchBlock2.java
System.out.println(a[10]);
catch(ArithmeticException e)
catch(ArrayIndexOutOfBoundsException e)
catch(Exception e)
Output:
In Java, using a try block inside another try block is permitted. It is called as nested try block. Every statement that we enter
a statement in try block, context of that exception is pushed onto the stack.
For example, the inner try block can be used to handle ArrayIndexOutOfBoundsException while the outer try block can
handle the ArithemeticException (division by zero).
Sometimes a situation may arise where a part of a block may cause one error and the entire block itself may cause another
error. In such cases, exception handlers have to be nested.
Syntax:
....
try
statement 1;
statement 2;
try
statement 3;
statement 4;
try
statement 5;
statement 6;
catch(Exception e2)
//exception message
catch(Exception e1)
//exception message
//exception message
....
Example 1
Let's see an example where we place a try block within another try block for two different exceptions.
NestedTryBlock.java
try{
try{
int b =39/0;
catch(ArithmeticException e)
System.out.println(e);
try{
a[5]=4;
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println(e);
System.out.println("other statement");
catch(Exception e)
System.out.println("normal flow..");
When any try block does not have a catch block for a particular exception, then the catch block of the outer (parent) try
block are checked for that exception, and if it matches, the catch block of outer try block is executed.
If none of the catch block specified in the code is unable to handle the exception, then the Java runtime system will handle
the exception. Then it displays the system generated message for that exception.
class Nesting {
// main method
// main try-block
try {
// try-block2
try {
// try-block3
try {
int arr[] = { 1, 2, 3, 4 };
System.out.println(arr[10]);
catch (ArithmeticException e) {
System.out.println("Arithmetic exception");
System.out.println(" try-block1");
catch (ArithmeticException e) {
System.out.println("Arithmetic exception");
System.out.println(" try-block2");
System.out.print("ArrayIndexOutOfBoundsException");
System.out.print("Exception");
Output:
ArrayIndexOutOfBoundsException main try-block
Built-in exceptions are the exceptions which are available in Java libraries.
Exceptions that are already available in Java libraries are referred to as built-in exception. These exceptions are able to
define the error situation so that we can understand the reason of getting this error. It can be categorized into two broad
categories, i.e., checked exceptions and unchecked exception.
Arithmetic exception :It is thrown when an exceptional condition has occurred in an arithmetic operation.
// ArithmeticException
class ArithmeticException_Demo {
try {
int a = 30, b = 0;
catch (ArithmeticException e) {
Output:
ArrayIndexOutOfBounds Exception : It is thrown to indicate that an array has been accessed with an illegal index. The index
is either negative or greater than or equal to the size of the array.
Example 2
// ArrayIndexOutOfBoundException
class ArrayIndexOutOfBound_Demo {
{
try {
// size 5
catch (ArrayIndexOutOfBoundsException e) {
Output:
In Java, we can create our own exceptions that are derived classes of the Exception class. Creating our own Exception is
known as custom exception or user-defined exception. Basically, Java custom exceptions are used to customize the
exception according to user need.
An exception is an issue (run time error) that occurred during the execution of a program. When an exception occurred the
program gets terminated abruptly and, the code past the line that generated the exception never gets executed.
Java provides us the facility to create our own exceptions which are basically derived classes of Exception. Creating our own
Exception is known as a custom exception or user-defined exception. Basically, Java custom exceptions are used to
customize the exception according to user needs. In simple words, we can say that a User-Defined Exception or custom
exception is creating your own exception class and throwing that exception using the ‘throw’ keyword.
Business logic exceptions: These are the exceptions related to business logic and workflow. It is useful for the application
users or the developers to understand the exact problem.
In order to create a custom exception, we need to extend the Exception class that belongs to java.lang package.
// Driver Program
try {
System.out.println("Caught");
System.out.println(ex.getMessage());
Output
Caught
Null
THREAD
A Thread is a very light-weighted process, or we can say the smallest part of the process that allows a program to operate
more efficiently by running multiple tasks simultaneously. In a program or process, all the threads have their own separate
path for execution, so each thread of a process is independent.
MULTITHREADING
Another benefit of using thread is that if a thread gets an exception or an error at the time of its execution, it doesn't affect
the execution of the other threads. All the threads share a common memory and have their own stack, local variables and
program counter. When multiple threads are executed in parallel at the same time, this process is known as Multithreading.
Feature through which we can perform multiple activities within a single process.
Lightweight process.
Thread Model
Just like a process, a thread exists in several states. These states are as follows:
1) New (Ready to run)
2) Running
3) Suspended
4) Blocked
5) Terminated
A thread comes in this state when at any given time, it halts its execution immediately.
Creating Thread
A thread is created either by "creating or implementing" the Runnable Interface or by extending the Thread class. These are
the only two ways through which we can create a thread.
Thread Class
A Thread class has several methods and constructors which allow us to perform various operations on a thread. The Thread
class extends the Object class. The Object class implements the Runnable interface. The thread class has the following
constructors that are used to perform various operations.
Thread()
Thread(Runnable target)
The Runnable interface is required to be implemented by that class whose instances are intended to be executed by a
thread. The runnable interface gives us the run() method to perform an action for the thread.
start() method
The method is used for starting a thread that we have newly created. It starts a new thread with a new callstack. After
executing the start() method, the thread changes the state from New to Runnable. It executes the run() method when the
thread gets the correct time to execute it.
Java Threads
Threads allows a program to operate more efficiently by doing multiple things at the same time.
Threads can be used to perform complicated tasks in the background without interrupting the main program.
Creating a Thread
It can be created by extending the Thread class and overriding its run() method:
Extend Syntax
Implement Syntax
Running Threads
If the class extends the Thread class, the thread can be run by creating an instance of the class and call its start() method:
Extend Example
thread.start();
OUTPUT
If the class implements the Runnable interface, the thread can be run by passing an instance of the class to a Thread
object's constructor and then calling the thread's start() method:
Implement Example
thread.start();
OUTPUT
Whenever we create a thread in Java, it always has some priority assigned to it. Priority can either be given by JVM while
creating the thread or it can be given by the programmer explicitly.
Priorities in threads is a concept where each thread is having a priority which in layman’s language one can say every object
is having priority here which is represented by numbers ranging from 1 to 10.
We will use currentThread() method to get the name of the current thread. User can also use setName() method if he/she
wants to make names of thread as per choice for understanding purposes.
1.public final int getPriority(): java.lang.Thread.getPriority() method returns priority of given thread.
2.public final void setPriority(int newPriority):java.lang.Thread.setPriority() method changes the priority of thread to the
value newPriority. This method throws IllegalArgumentException if value of parameter newPriority goes beyond
minimum(1) and maximum(10) limit.
Example
import java.lang.*;
// Main class
// Method 1
// Print statement
// Thread 1
+ t1.getPriority());
// Thread 1
+ t2.getPriority());
// Thread 3
+ t3.getPriority());
t1.setPriority(2);
t2.setPriority(5);
t3.setPriority(8);
// IllegalArgumentException
// 2
+ t1.getPriority());
// 5
+ t2.getPriority());
// 8
+ t3.getPriority());
// Main thread
System.out.println(
+ Thread.currentThread().getName());
System.out.println(
+ Thread.currentThread().getPriority());
System.out.println(
+ Thread.currentThread().getPriority());
Output
t1 thread priority : 5
t2 thread priority : 5
t3 thread priority : 5
t1 thread priority : 2
t2 thread priority : 5
t3 thread priority : 8
Output explanation:
Thread with the highest priority will get an execution chance prior to other threads. Suppose there are 3 threads t1, t2, and
t3 with priorities 4, 6, and 1. So, thread t2 will execute first based on maximum priority 6 after that t1 will execute and then
t3.The default priority for the main thread is always 5, it can be changed later. The default priority for all other threads
depends on the priority of the parent thread.
import java.lang.*;
// Main class
// ThreadDemo
// Method 1
// Print statement
// Method 2
Thread.currentThread().setPriority(6);
System.out.println(
+ Thread.currentThread().getPriority());
// main()
+ t1.getPriority());
Output
t1 thread priority : 6
Output explanation:
If two threads have the same priority then we can’t expect which thread will execute first. It depends on the thread
scheduler’s algorithm(Round-Robin, First Come First Serve, etc)
If we are using thread priority for thread scheduling then we should always keep in mind that the underlying platform
should provide support for scheduling based on thread priority.
Synchronization in Java
Synchronization in Java is the capability to control the access of multiple threads to any shared resource.
Java Synchronization is better option where we want to allow only one thread to access the shared resource.
Types of Synchronization
1.Process Synchronization
2.Thread Synchronization
Thread Synchronization
There are two types of thread synchronization mutual exclusive and inter-thread communication.
1.Mutual Exclusive
a.Synchronized method.
b.Synchronized block.
c.Static synchronization.
Mutual Exclusive
Mutual Exclusive helps keep threads from interfering with one another while sharing data. It can be achieved by using the
following three ways:
Synchronization is built around an internal entity known as the lock or monitor. Every object has a lock associated with it. By
convention, a thread that needs consistent access to an object's fields has to acquire the object's lock before accessing
them, and then release the lock when it's done with them.
In this example, there is no synchronization, so output is inconsistent. Let's see the example:
TestSynchronization1.java
class Table{
for(int i=1;i<=5;i++){
System.out.println(n*i);
try{
Thread.sleep(400);
}catch(Exception e){System.out.println(e);}
Table t;
MyThread1(Table t){
this.t=t;
t.printTable(5);
}
class MyThread2 extends Thread{
Table t;
MyThread2(Table t){
this.t=t;
t.printTable(100);
class TestSynchronization1{
t1.start();
t2.start();
Output:
100
10
200
15
300
20
400
25
500
Java Synchronized Method
When a thread invokes a synchronized method, it automatically acquires the lock for that object and releases it when the
thread completes its task.
TestSynchronization2.java
class Table{
for(int i=1;i<=5;i++){
System.out.println(n*i);
try{
Thread.sleep(400);
}catch(Exception e){System.out.println(e);}
Table t;
MyThread1(Table t){
this.t=t;
t.printTable(5);
Table t;
MyThread2(Table t){
this.t=t;
t1.start();
t2.start();
Output:
10
15
20
25
100
200
300
400
500
Inter-thread communication or Co-operation is all about allowing synchronized threads to communicate with each other.
Cooperation (Inter-thread communication) is a mechanism in which a thread is paused running in its critical section and
another thread is allowed to enter (or lock) in the same critical section to be executed. It is implemented by following
methods of Object class:
1.wait()
2.notify()
3.notifyAll()
1) wait() method
The wait() method causes current thread to release the lock and wait until either another thread invokes the notify()
method or the notifyAll() method for this object, or a specified amount of time has elapsed.
The current thread must own this object's monitor, so it must be called from the synchronized method only otherwise it will
throw exception.
Method Description
public final void wait(long timeout)throws It waits for the specified amount of time.
InterruptedException
2) notify() method
The notify() method wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this
object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation.
Syntax:
3) notifyAll() method
Syntax:
3.Now thread goes to waiting state if you call wait() method on the object. Otherwise it releases the lock and exits.
4.If you call notify() or notifyAll() method, thread moves to the notified state (runnable state).
5.Now thread is available to acquire lock.
6.After completion of the task, thread releases the lock and exits the monitor state of the object.
Why wait(), notify() and notifyAll() methods are defined in Object class not Thread class?
wait() sleep()
The wait() method releases the lock The sleep() method doesn't release the lock.
It is a method of Object class It is a method of Thread class
It should be notified by notify() or notifyAll() methods After the specified amount of time, sleep is completed.
Test.java
class Customer{
int amount=10000;
System.out.println("going to withdraw...");
if(this.amount<amount){
try{wait();}catch(Exception e){}
this.amount-=amount;
System.out.println("withdraw completed...");
System.out.println("going to deposit...");
this.amount+=amount;
notify();
}
class Test{
new Thread(){
}.start();
new Thread(){
}.start();
}}
Output:
going to withdraw...
going to deposit...
deposit completed...
withdraw completed
Thread.stop() is being phased out due to its inherent risk. When you stop a thread, it unlocks all the monitors it has locked.
Other threads might see these objects in an inconsistent state if any of the objects previously protected by these monitors
were in an inconsistent state.
Threads acting on damaged objects can act erratically, whether consciously or unconsciously. ThreadDeath, unlike other
uncontrolled exceptions, silently kills threads, leaving the user with no warning that the program may be corrupted. After
the damage has occurred, the corruption may appear at an unpredicted moment. Also, killing a thread will create a
problem while working with DBMS – JDBC in a multithreaded environment.
class NumVal {
int i = 0;
NumVal()
if (i < 9) {
num[i] = n;
i++;
if (i >= 0) {
i--;
else {
return -1;
}
// Creating Our Thread Class
// Constructor
super(threadName);
NumObjToSetVal = numV;
// referred by : NumObjToSetVal
synchronized (NumObjToSetVal)
int n = 0;
while (n < 5) {
System.out.println(
+ Thread.currentThread().getName());
n++;
NumObjToSetVal.setVal(n);
try {
Thread.sleep(100);
System.out.println(
Thread.currentThread().getName()
+ "is awake now");
catch (Exception e) {
System.out.println("Exception Caught");
if (n == 2) {
// waiting state
Thread.currentThread().suspend();
// object referred by v
// object referred by v
thread1.start();
thread2.start();
Output:
Explanation: We created 2 threads: thread1 & thread2. Both want to acquire a lock on the NumVal object referred to by ‘v’
reference.
As we start both the threads by calling the start() method, the run() method will execute whenever the thread gets CPU.
Thread1 gets CPU & when the value of n is 2 in its run method, the thread is suspended. Thread1 is not going to release
lock on Object referred by ‘v’ until resume() is called on it.
For thread2 to acquire a lock on v Object referred by ‘v’, thread1 must have released the lock on Object referred by ‘v’. Here
the lock here is not released, thread2 will keep on waiting for thread1 to release the lock on the object referred by ‘v’ & a
deadlock will be formed.
So, you have always call resume() on a thread (at any time) whenever you call suspend() method on the same thread.
Multithreading in Java
Multithreading in Java is a process of executing multiple threads simultaneously.
A thread is a lightweight sub-process, the smallest unit of processing. Multiprocessing and multithreading, both are used to
achieve multitasking.
However, we use multithreading than multiprocessing because threads use a shared memory area. They don't allocate
separate memory area so saves memory, and context-switching between the threads takes less time than process.
1) It doesn't block the user because threads are independent and you can perform multiple operations at the same time.
3) Threads are independent, so it doesn't affect other threads if an exception occurs in a single thread.
Multitasking
Multitasking is a process of executing multiple tasks simultaneously. We use multitasking to utilize the CPU. Multitasking
can be achieved in two ways:
Each process has an address in memory. In other words, each process allocates a separate memory area.
A process is heavyweight.
Switching from one process to another requires some time for saving and loading registers, memory maps, updating lists,
etc.
A thread is lightweight.
A thread is a lightweight subprocess, the smallest unit of processing. It is a separate path of execution.
Threads are independent. If there occurs exception in one thread, it doesn't affect other threads. It uses a shared memory
area.
try {
System.out.println(
+ " is running");
catch (Exception e) {
// Throwing an exception
System.out.println("Exception is caught");
// Main Class
MultithreadingDemo object
= new MultithreadingDemo();
object.start();
Output
Thread 15 is running
Thread 14 is running
Thread 16 is running
Thread 12 is running
Thread 11 is running
Thread 13 is running
Thread 18 is running
Thread 17 is running
We create a new class which implements java.lang.Runnable interface and override run() method. Then we instantiate a
Thread object and call start() method on this object.
try {
System.out.println(
+ " is running");
catch (Exception e) {
// Throwing an exception
System.out.println("Exception is caught");
// Main Class
class Multithread {
object.start();
Output
Thread 13 is running
Thread 11 is running
Thread 12 is running
Thread 15 is running
Thread 14 is running
Thread 18 is running
Thread 17 is running
Thread 16 is running
If we extend the Thread class, our class cannot extend any other class because Java doesn’t support multiple inheritance.
But, if we implement the Runnable interface, our class can still extend other base classes.
We can achieve basic functionality of a thread by extending Thread class because it provides some inbuilt methods like
yield(), interrupt() etc. that are not available in Runnable interface.
Using runnable will give you an object that can be shared amongst multiple threads.
The wrapper class in Java provides the mechanism to convert primitive into object and object into primitive.
Java is an object-oriented programming language, so we need to deal with objects many times like in Collections,
Serialization, Synchronization, etc. Let us see the different scenarios, where we need to use the wrapper classes.
Change the value in Method: Java supports only call by value. So, if we pass a primitive value, it will not change the original
value. But, if we convert the primitive value in an object, it will change the original value.
Serialization: We need to convert the objects into streams to perform the serialization. If we have a primitive value, we can
convert it in objects through the wrapper classes.
java.util package: The java.util package provides the utility classes to deal with objects.
Collection Framework: Java collection framework works with objects only. All classes of the collection framework (ArrayList,
LinkedList, Vector, HashSet, LinkedHashSet, TreeSet, PriorityQueue, ArrayDeque, etc.) deal with objects only.
Java Wrapper Classes
Wrapper classes provide a way to use primitive data types (int, boolean, etc..) as objects.
The table below shows the primitive type and the equivalent wrapper class:
byte Byte
short Short
int Integer
long Long
float Float
double Double
boolean Boolean
char Character
To create a wrapper object, use the wrapper class instead of the primitive type. To get the value, you can just print the
object:
Example
Integer myInt = 5;
System.out.println(myInt);
System.out.println(myDouble);
System.out.println(myChar);
OUTPUT
5.99
Since you're now working with objects, you can use certain methods to get information about the specific object.
For example, the following methods are used to get the value associated with the corresponding wrapper object: intValue(),
byteValue(), shortValue(), longValue(), floatValue(), doubleValue(), charValue(), booleanValue().
Another useful method is the toString() method, which is used to convert wrapper objects to strings.
In the following example, we convert an Integer to a String, and use the length() method of the String class to output the
length of the "string":
Example
System.out.println(myString.length());
OUTPUT
There are certain needs for using the Wrapper class in Java as mentioned below:
1.They convert primitive data types into objects. Objects are needed if we wish to modify the arguments passed into a
method (because primitive types are passed by value).
2.The classes in java.util package handles only objects and hence wrapper classes help in this case also.
3.Data structures in the Collection framework, such as ArrayList and Vector, store only objects (reference types) and not
primitive types.
2.On object data we can call multiple methods compareTo(), equals(), toString()
The automatic conversion of primitive data types into its equivalent Wrapper type is known as boxing and opposite
operation is known as unboxing.
Advantage of Autoboxing and Unboxing:
No need of conversion between primitives and Wrappers manually so less coding is required.
class BoxingExample1{
int a=50;
Integer a3=5;//Boxing
System.out.println(a2+" "+a3);
Output:50 5
The automatic conversion of wrapper class type into corresponding primitive type, is known as Unboxing.
class UnboxingExample1{
int a=i;
System.out.println(a);
Output:
50
class UnboxingExample2{
System.out.println(i);
Output:50
In method overloading, boxing and unboxing can be performed. There are some rules for method overloading with boxing:
class Boxing1{
short s=30;
m(s);
Output:int
class Boxing2{
static void m(int i, int i2){System.out.println("int int");}
short s1=30,s2=40;
m(s1,s2);
Output:int int
class Boxing3{
int a=30;
m(a);
Output:Integer
class Boxing4{
int a=30;
m(a);
}
Output:Compile Time Error
In autoboxing, the Java compiler automatically converts primitive types into their corresponding wrapper class objects. For
example,
int a = 56;
// autoboxing
Integer aObj = a;
import java.util.ArrayList;
class Main {
//autoboxing
list.add(5);
list.add(6);
Output
ArrayList: [5, 6]
In the above example, we have created an array list of Integer type. Hence the array list can only hold objects of Integer
type.
list.add(5);
Here, we are passing primitive type value. However, due to autoboxing, the primitive value is automatically converted into
an Integer object and stored in the array list.