Java Unit-Iii
Java Unit-Iii
UNIT-3
A software Engineer may also commit several errors while designing the
project or developing the code. These errors are also called bugs and the
process of removing them is called “debugging”.
Compile-time errors:
The Compile-Time Errors are syntactical errors in the code, due to
which the program fails to compile. Let us consider the following java
program in which the compiler gives an error.
import java.lang.*;
class D
{
public static void main(String args[])
{
int a=0,b=9;
System.out.println(a+"\t"+b);
System.out.println("Hello ");
System.out.println();
}
}
Logical Errors:
The logical errors depict the flaws in the logic of the program. The
programmer might be using a wrong formula or the design of the program
itself is wrong. Logical errors are not detected either by Java compiler or
JVM. Let us consider the following program in which instead of addition
subtraction operation is performed.
import java.lang.*;
class Demo
{
public static void main(String args[])
{
int a=10,b=9;
System.out.println("sum of two numbers :"+(a-b));
}
}
Runtime Error:
The error that occurs at the execution time is called Runtime Error.
import java.lang.*;
class D
{
public static void main()
{
int a=0,b=9; System.out.println(a+"\t"+b);
System.out.println("Sum of Two Numbers : "+(a+b));
}
}
Exception:
An Exception is a Runtime Error. An Exception is an abnormal and
unexcepted and also unwanted event that disturbs the normal flow of the
program. All Exceptions occur only at runtime but some exceptions are
detected at compile time and some others at runtime. The exceptions that
are checked at compilation time by the java compiler are called checked
exceptions while the exceptions that are checked by the JVM are called
unchecked exception.
Ex: FileNotFoundException
ArithmeticException
class Demo
{
public static void main(String[] args)
{
int a=10,b=0,c;
System.out.println("hello");
c=a/b;
System.out.println(c);
System.out.println("Hello World!");
}
}
Types of Exceptions:
They are two types of Exceptions available in java
1. Built-in-Exception
2. User-defined Exception
Built-in-Exception:
Built-in-Exceptions are which already available in java. These Exceptions
are suitable to explain certain error situations.
Checked Exception:
The classes which directly inherit Throwable class except both
RuntimeException and Error are known as checked exceptions
Ex: IOException,
SQLException
Unchecked Exception:
The classes which inherit RuntimeException are known as unchecked
exceptions
Ex: ArithmeticException,
NullPointerException,
ArrayIndexOutOfBoundsException.
Error:
Error is irrecoverable
Ex: OutOfMemoryError
VirtualMachineError
AssertionError
Exception models:
Termination Model
Resumptive Model
Termination Model:
In other words we can say that in termination model the error is so critical
there is no way to get back to where the exception occurred.
Resumptive Model:
In resumptive model we may use a method call that want resumption like
behavior. We may also place the try block in a while loop that keeps re-
entering the try block until the result is satisfactory.
Uncaught Exceptions:
The uncaught exceptions are the exceptions that are not caught by the
compiler but automatically caught and handled by the Java built-in
exception handler.
When an uncaught exception occurs, the JVM calls a special private method
known dispatchUncaughtException( ), on the Thread class in which the
exception occurs and terminates the thread.
import java.lang.*;
class Demo
{
public static void main(String[] args)
{
int a=10,b=0,c;
System.out.println("hello");
c=a/b;
System.out.println(c);
System.out.println("Hello World!");
}
}
Exceptions are the conditions that occur at runtime and may cause
the termination of program. But they are recoverable using Exception
Handling Mechanism. Exceptions can be handled by using five keywords.
try:
Identify the statements that may trouble at runtime and place them in
the try block
catch:
When the try block throws the exception the catch block handles the
exception. If the try block does not throw the exception the catch block is
simply ignored.
try
{
//code that may throw an exception
}
catch(Exception_class_Name ref)
{
// Handles Exception raised in Try Block
}
import java.lang.*;
class Demo
{
public static void main(String[] args)
{
int a=10,b=0,c;
System.out.println("hello");
c=a/b;
System.out.println(c);
System.out.println("Hello World!");
}
}
class Demo1
{
public static void main(String[] args)
{
int a=100,b=0,c; System.out.println("hello1 ");
try
{
c=a/b;
System.out.println(c);
}
catch(ArithmeticException e)
{
System.out.println(" Do Not Divide by Zero "+e);
}
System.out.println("hello1");
System.out.println("Hello2");
}
}
import java.lang.*;
class Demo1
{
public static void main(String args[])
{
int x[]={10,20,30};
System.out.println("hello1");
try
{
System.out.println(x[3]);
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println(e);
System.out.println("hello2");
System.out.println("hello3");
}
}
class Demo2
{
public static void main(String args[])
{
String s="abc";
try
{
System.out.println(s.charAt(3));
}
catch(StringIndexOutOfBoundsException e)
{
System.out.println("Access out of its range");
}
}
}
import java.lang.*;
class NumberF
{
public static void main(String args[])
{
try
{
int a = Integer.parseInt(args[0]);
System.out.println("FIRST ARGUMENT "+a);
int b = Integer.parseInt(args[1]);
System.out.println("second ARGUMENT "+b);
int c = Integer.parseInt(args[2]);
System.out.println(a+"\t"+b+"\t"+c);
}
catch(NumberFormatException e)
{
System.out.println("unable to convert from string to int ");
}
}
}
In the above program we are passing three argument to the main method as
Strings out of which two arguments we can convert into integer but third
argument cannot converted from string to int so for third argument
NumberFormatException raised.
class Demo4
{
public static void main(String args[])
{
String s1=null;
try
{
System.out.println(s1.length());
}
catch(NullPointerException e)
{
System.out.println(e);
}
}
}
class Demo5
{
public static void main(String args[])
{
try
{
int x[]= new int[-7];
}
catch(NegativeArraySizeException e)
{
System.out.println(e);
}
}
}
class Demo1
{
public static void main(String[] args)
{
int a=100,b=0,c; int s[]={10,30,40};
System.out.println("hello1 "); try
{
c=a/b; System.out.println(c); System.out.println(s[5]);
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println(e);
}
System.out.println("hello1"); System.out.println("Hello2");
}
}
A try block can be followed by one or more catch blocks. Each catch block
must contain a different exception handler. So, if you have to perform
different tasks at the occurrence of different exceptions, use java multi-catch
block.
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.
try
{
---
}
catch(ArithmeticException ae)
{
---
}
catch(Exception e)
{
---
}
class Demo1
{
public static void main(String[] args)
{
int a=100,b=0,c;
int s[]={10,30,40};
System.out.println("hello1 ");
try
{
c=a/b;
System.out.println(c);
System.out.println(s[5]);
}
catch(ArithmeticException e)
{
System.out.println(e);
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println(e);
}
System.out.println("hello1");
System.out.println("Hello2");
}
}
The try block within a try block is known as nested try block in java.
try
{
statement 1;
statement 2;
try
{
statement 1;
statement 2;
}
catch(Exception e)
{
}
}
catch(Exception e)
{
class Demo
{
public static void main(String args[])
{
int a=10,b=0,c;
String s;
try
{
try
{
s=null;
//trying to print the character at index 0 of the string s
System.out.println(s.charAt(0));
}
catch(NullPointerException np)
{
System.out.println(np);
}
c=a/b;
System.out.println(c);
}
catch(ArithmeticException e)
{
System.out.println(e);
}
System.out.println("Exception are Handled");
}
}
import java.io.*;
class Demo1
{
public static void main(String args[])throws IOException
{
try
{
try
{ //nested try block1
System.out.println("going to divide");
int b =39/0;
}
catch(ArithmeticException e)
{
System.out.println("Arithmetic Exception is Raised");
}
try
{ //nested try block2
int a[]=new int[5]; //index range : 0 to 4
a[5]=4;// trying to assigned array value at index 5
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println(e);
}
{
System.out.println("Exceptions are handeled");
}
System.out.println("normal flow..");
}
}
Finally block:
In order to perform clean up operations like closing files and
terminating of threads the programmer has to write that particular code in
the finally block.
try
{
//code that may throw an exception
}
catch(Exception_class_Name ref)
{
// Handles Exception raised in Try Block
}
finally
{
// executes before try block ends
}
The statements inside the finally block are executed irrespective of whether
there is an exception or not. This ensures that all the opened files are
properly closed and all running threads are properly terminated.
class Demo1
{
public static void main(String[] args)
{
int a=100,b=0,c;
int s[]={10,30,40};
System.out.println("hello1 ");
try
{
c=a/b;
System.out.println(c);
System.out.println(s[5]);
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println(e);
}
finally
{
System.out.println("Closing of files");
}
System.out.println("hello1");
System.out.println("Hello2");
}
}
Let us consider the following program in which both exceptions are raised
and handled with catch blocks.
class Demo1
{
public static void main(String[] args)
{
int a=100,b=0,c;
int s[]={10,30,40};
System.out.println("hello1 ");
try
{
c=a/b;
System.out.println(c);
System.out.println(s[5]);
}
catch(ArithmeticException e)
{
System.out.println(e);
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println(e);
}
finally
{
System.out.println("Closing of files");
}
System.out.println("hello1");
System.out.println("Hello2");
}
}
Throws:
Even if the programmer is not handling the runtime exceptions, the
java compiler will not give any error related to runtime exceptions. But the
rule is that the programmer should handle checked exceptions. In case the
programmer does not want to handle the exceptions, he should throw them
out using throws clause. throws is keyword in java.
import java.lang.*;
import java.io.*;
class Demo1
{
public static void main(String[] args)
{
int a,b;
BufferedReader br = new BufferedReader(new InputStreamReader
(System.in));
System.out.println("Enter Integer ");
a=Integer.parseInt(br.readLine());
System.out.println("Enter another Integer");
b=Integer.parseInt(br.readLine());
System.out.println("sum of two numbers : "+(a+b));
System.out.println("Division of two numbers : "+(a/b));
}
}
The above program will not compile since there is a possibility that
readLine() raises an IOException which is a checked exception.
import java.lang.*;
import java.io.*;
class Demo1
{
public static void main(String[] args)
{
int a,b;
try
{
BufferedReader br = new BufferedReader(new InputStreamReader
(System.in));
System.out.println("Enter Integer ");
a=Integer.parseInt(br.readLine());
System.out.println("Enter another Integer");
b=Integer.parseInt(br.readLine());
System.out.println("sum of two numbers : "+(a+b));
System.out.println("Division of two numbers : "+(a/b));
}
catch(IOException e)
{
System.out.println(e);
}
}
}
In the above program the exception is handled by using try, catch keywords.
import java.lang.*;
import java.io.*;
class Demo1
{
public static void main(String[] args)throws IOException
{
int a,b;
BufferedReader br = new BufferedReader(new InputStreamReader
(System.in));
System.out.println("Enter Integer ");
a=Integer.parseInt(br.readLine());
System.out.println("Enter another Integer");
b=Integer.parseInt(br.readLine());
System.out.println("sum of two numbers : "+(a+b));
System.out.println("Division of two numbers : "+(a/b));
}
}
In the above program the exception is not handled by using try and catch
but the exception is throw out of the method by using throws keyword.
import java.lang.*;
import java.io.*;
class Demo1
{
int a,b; // instace variable
public void accept()throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader
(System.in));
System.out.println("Enter Integer ");
a=Integer.parseInt(br.readLine());
System.out.println("Enter another Integer");
b=Integer.parseInt(br.readLine());
}
public void display()
{
System.out.println(a+"\t"+b);
}
public static void main(String[] args)throws IOException
{
Demo1 d = new Demo1();
d.accept();
d.display();
}
}
throw:
throw is keyword in java used to throw an exception explicitly and
catch it. Throw must be used only inside the try block otherwise compiler
gives an error.
class Sample
{
static void demo()
{
try
{
System.out.println("Inside Demo");
throw new NullPointerException("Throw Demo");
}
catch(NullPointerException ne)
{
System.out.println(ne);
}
}
}
class ThrowDemo
{
public static void main(String args[])
{
Sample.demo();
}
}
2. Take one parameter constructor that takes the string as the arugument
and call super class constructor.
import java.io.*;
class NoMoneyException extends Exception
{
public NoMoneyException(String msg)
{
super(msg);
}
}
class Demo7
{
public static void main(String args[])throws IOException
{
int bal=15000,withdraw;
BufferedReader br = new BufferedReader(new InputStreamReader
(System.in));
System.out.println("Welcome to XXX Bank Services");
System.out.println("Enter Amount");
withdraw=Integer.parseInt(br.readLine());
try
{
if(bal<withdraw)
{
throw new NoMoneyException("sorry unable to process");
}
else
{
System.out.println("Please Wait U r Transaction being processing ");
}
}
catch(NoMoneyException e)
{
System.out.println(e);
}
System.out.println("Welcome to XXX Bank Services");
}
}
Multithreading
Thread:
A thread represents a separate path of execution of a group of
statements. In java if we write a group of statements, then these statements
are executed by jvm one-by-one. This means that in every java program
there is always a thread running internally.
Process-based Multitasking
Thread-based Multitasking
Uses of Threads:
Threads can be used for multiple purpose. Some of the uses of threads
are:
In server-side programs to serve the needs of multiple clients on a
network or internet.
To create games and animation. Animation means moving the objects
from one place to another.
Multithreading:
Multithreading refers to two or more tasks executing concurrently
within a single program. A java process can be divided into a number of
threads and each thread can be given a different task.
Creating a Thread:
We know that in every java program, there is a main thread available
already. Apart from this main thread, we can also create our own threads in
a program.
sleep():
sleep() is a static method of Thread class which makes a running
thread to become inactive for the specified time in milli seconds passed as a
parameter.When the sleep() time is over the thread implicitly becomes active.
Note: A thread executes only the code inside the main() method. It never
execute other methods unless they are called from run().
for(int i=1;i<=10;i++)
{
System.out.println(str+" : "+i);
try
{
Thread.sleep(1000);
}
catch(InterruptedException ie)
{
System.out.println(ie);
}
}
}
public static void main(String args[])
{
MultiTasking d = new MultiTasking("show the ticket");
MultiTasking d1= new MultiTasking("cut the ticket");
Thread t = new Thread(d);
Thread t1=new Thread(d1);
t.start();
t1.start();
}
}
t.start();
t1.start();
}
}
Thread Synchronization:
When a thread is already acting on an object, preventing any other
thread from acting on the same object is called Thread Synchronization or
Thread Safe. The object on which the threads are synchronized is called
synchronized object. Thread synchronization is recommended when multiple
threads are used on the same object
Syntax:
Synchronized(obj)
{
Statements;
}
Syntax:
Synchronized void method()
{
Statements;
}
t.start();
t1.start();
}
}
The following figure shows the different states of thread in Life Cycle:
Ready/Runnable state :
when we call start() method on a thread the thread enters into ready /
runnable state. In this state the thread is active and it is eligible for
microprocessor time. All threads are waiting in the thread pool for
microprocessor time. The thread scheduler fixs the thread and give to the
processor.
Running state:
A thread is in running state if it is utilizing the micro processor time. There
are several ways to enter into the runnable state but there is only one way to
enter in running state.
Dead state:
when the thread execution is completed the thread enters into dead state.
Sleeping state:
When we call sleep() method on the executing thread the threads enters into
sleeping state and when the sleep interval expires automatically the thread
enters into the running state.
Waiting state:
Waiting state when we call wait() method on the thread the thread enters
into waiting state. When we call notify() or notifyall() methods the thread
enters into ready or runnable state.
Priorities of Threads:
Each thread has a priority, which helps the thread scheduler to decide
the order of sequence of thread execution i.e, whhen should which thread
run? By default the threads created, carry the same priority, due to which
java scheduler schedules them for the processor on FirstComeFirstServe
basis. Java follows preemptive sheduling policy like OS.
Threads can be given different priorities from 1 to 10. The thread with
more priority is given first preference by thread scheduler of JVM. The
thread scheduler of JVM allocates more microprecssor time than the thread
with less priority.
//setting priorities
tp.setPriority(Thread.MIN_PRIORITY);
tp1.setPriority(Thread.MIN_PRIORITY+3);
tp2.setPriority(Thread.MAX_PRIORITY);
//getting priorities
System.out.println("First Thread Priority : "+tp.getPriority());
System.out.println("Second Thread Priority : "+tp1.getPriority());
System.out.println("Third Thread Priority : "+tp2.getPriority());
tp.setName("first thread ");
tp1.setName("second thread ");
tp2.setName("third thread ");
tp.start();
tp1.start();
tp2.start();
}
}
class Communicate
{
public static void main(String args[])
{
Producer po=new Producer();
Consumer co=new Consumer(po);
Thread t1=new Thread(po);
Thread t2=new Thread(co);
t2.start();
t1.start();
}
}
class Producer extends Thread
{
StringBuffer sb;
boolean dover=false;
Producer()
{
sb=new StringBuffer();
}
public void run()
{
for(int i=1;i<=10;i++)
{
try{
sb.append(i+" ");
Thread.sleep(100);
System.out.println("Still Appending");
}
catch(InterruptedException e){System.out.println(e);}
}
dover=true;
System.out.println("Data Production is Completed");
}
}
class Consumer extends Thread
{
Producer prod;
Consumer(Producer prod)
{
this.prod=prod;
}
public void run()
{
try {
while(!prod.dover)
{
Thread.sleep(10);
}
}
catch(InterruptedException e) { }
System.out.println("Produced Data is");
System.out.println(prod.sb);
}
}
In this way, the producer and consumer can communicate with each
other. But this is not an efficient way of communication. Why? Consumer
checks the dataprodover at some point of time and finds it false. So it goes
into sleep for the next 10milliseconds. Meanwhile the data production may
be over. But consumer comes out of sleep after 10 milliseconds and then
only it can find dataprodover is true. This means that there may be a time
delay of 1 to 9 milliseconds to receive the data after its actual production is
completed.
wait(): This method makes a thread wait for the object till it receives a
notification from a notify() and notifyAll().
class Communicate1
{
public static void main(String args[])
{
Producer obj1=new Producer();
Consumer obj2=new Consumer(obj1);
Thread t1=new Thread(obj1);
Thread t2=new Thread(obj2);
t2.start();
t1.start();
}
}
class Producer extends Thread
{
StringBuffer sb;
boolean dataprodover=false;
Producer()
{
sb=new StringBuffer();
}
public void run()
{
synchronized(sb)
{
for(int i=1;i<=10;i++)
{
try{
sb.append(i+" ");
Thread.sleep(100);
System.out.println("appending");
}
catch(Exception e){ }
}
sb.notify();
}
}
}
class Consumer extends Thread
{
Producer prod;
Consumer(Producer prod)
{
this.prod=prod;
}
public void run()
{
synchronized(prod.sb)
{
try{
prod.sb.wait();
}
catch(InterruptedException e){ }
System.out.println(prod.sb);
}
}
}