Java Notes PDF
Java Notes PDF
Java Notes PDF
CHAPTER 1
INTRODUCTION
Introduction
One characteristic that is constant in software today is “change”.
New tools and new approaches are announced almost every day.
To build today’s complex software it is just not enough to put together a sequence of programming
statements and sets of procedures and modules.
Object-Oriented Programming (OOP) is an approach to program organization and development, which
attempts to eliminate some of pitfalls of conventional programming methods by incorporating the best of
structured programming features with several new concepts.
It is a new way of organizing and developing programs and has nothing to do with and particular language.
Languages that support OOP features include C++, Java, Smalltalk.
Object-Oriented Paradigm
The major objective of object-oriented approach is to eliminate some of the flaws encountered in procedural
approach.
OOP treats data as critical element in program development and does not allow it to flow freely around
system.
Object-oriented programming is an approach that provides a way of modularizing programs by creating
partitioned memory area for both data and functions that can be used as templates for creating copies of
such modules on demand.
Some of the features of object-oriented paradigm are:
o Emphasis is on data rather than procedure
o Program are divided into what are known as objects
o Data structures are designed such that they characterize the objects.
o Methods that operate on data of an object are tied together in data structure.
o Data is hidden and cannot be accesses by external functions.
o Objects may communicate with each other through methods.
o New data and methods can be easily added whenever necessary.
o Follows bottom-up approach in program design.’
The data is not accessible to the outside world and only those methods, which are wrapped in class can
access it.
The insulation of data from direct access by the program is called data hiding.
Abstraction refers to the act of representing essential features without including the background details
or explanations.
Inheritance
Inheritance is the process by which objects of one class acquire the properties of another class.
This provides the idea of reusability.
This means that we can add additional features to an existing class without modifying it.
This is possible by deriving a new class from the existing one.
The new class will have the combined features of both the classes
Polymorphism
This means the ability to take more than one form.
For example, an operation may exhibit different behavior in different instance.
The behavior depends upon the types of data used in operation.
The following figure depicts this idea:
Dynamic binding
Binding refers to linking of procedure call to code to be executed in response to the call.
Dynamic binding means that the code associated with given procedure call is not known until the time
of call at runtime.
Message Communication
An object-oriented program consists of set of objects that communicate with each other.
The process of programming in an object-oriented language involves following steps:
1. Creating classes that define objects and their behavior.
2. Creating objects from that class definition
3. Establishing communication among objects.
Objects communicate with one another by sending and receiving information by calling the methods.
Benefits of OOP
The principle advantages are:
1. Through inheritance, redundant code is reduced and extends the use of existing class.
2. The principle of data hiding helps the programmer to build secure programs that cannot be invaded by
code in other parts of program.
3. It is possible to have multiple objects to coexist without any interference.
4. It is easy to partition the work in project based on objects.
5. Software complexity can be easily managed.
Applications of OOP
The promising areas for application of OOP include:
1. Real-time systems
2. Simulation and modeling
3. Object-orients databases
4. Hypertext, hypermedia and expertext
5. Al and expert systems
6. Neural networks and parallel programming
7. Decision support and office automation systems.
8. CIM/CAD/CAD systems.
3
Java History
Java is general-purpose, object oriented programming language developed by Sun Microsystems of USA in
1991
Originally called ‘Oak’ by James Gosling, one of the inventors of language.
The goal was to make language simple, portable and reliable.
The Java team included Patrick Naughton discovered that existing language like C and C++ had limitations.
They modeled their new language Java on C and C++ but removed number of features of C and C++ that
were considered as source of problems and thus made Java really simple, reliable, portable and powerful
language.
The most striking feature of language is that it is platform-neutral language.
Java is first language that is not tied to any particular hardware or operating system.
Java Features
The inventors of Java wanted the language to be not reliable, portable and distributed but also simple,
compact and interactive.
Sun Microsystems officially describes Java with the following attributes:
o Compiled and Interpreted
Usually computer language is either compiled or interpreted.
Java combines both these approaches thus making Java 2-stage system.
First, Java compiler translates source code into what is known as bytecode instructions
Bytecodes are not machine instructions and therefore, in second stage, Java interpreter generates
machine code that can be directly executed by machine that is running Java program.
o Object-Oriented
Java is true object-oriented language; almost everything in Java is an object.
All program code and data reside within objects and classes.
Java comes with extensive set of classes, arranged in packages that can be used in programs by
inheritance.
o Distributed
Java is designed as distributed language for creating applications on internet.
It has the ability to share both data and programs.
Java applications can open and access remote objects on internet as easily as they can do in local
systems.
o High Performance
Java programming is impressive for an interpreted language, due to the use of intermediate
bytecode.
Java architecture is also designed to reduce overheads during runtime.
The incorporation of multithreading enhances overall execution speed of Java programs.
HTML
Document Bytecode
Java Web Browser
HTML Document
User
The figure shows the following communication steps:
1. The user sends request for HTML document to remote computer’s Web Server. The Web Server is
program that accepts request, process request and sends required document.
2. HTML document is returned to user’s browser that contains APPLET tag, which identifies applet.
3. The corresponding applet bytecode is transferred to user’s computer.
4. The Java – enabled browser on user’s computer interprets bytecode and provides output.
5. The user may further interact with applet but with no further downloading from providers web server.
Java Environment
Java environment includes large number of development tools & hundreds of classes & methods
The development tools are part of system known as Java Development Kit and classes and methods are part
of the Java Standard Library ( JSL ), also known as Application Programming Interface ( API ).
Java Development Kit
The Java Development Kit comes with collection of tools that are used for developing and running Java
programs. They includes:
o appletviewer --- Enables to run Java applets.
o javac --- Java compiler, which translates Java sourcecode to bytecode.
o java--- Java interpreter, which runs the applet.
o javap --- Java disassembler, enables to convert bytecode files into programdescription.
o javah --- Produces header files for use with native mathods.
o javadoc --- creates HTML format documentation from Java source code files.
o jdb --- Java debugger, which helps us to find errors in our programs.
The way these tools are applied to build & run application programs is illustrated in below figure:
Test Editor
java jdb
Java Program
Output
To create Java program, we need to create source code file using text editor.
The source code is compiled using Java compiler ( javac ) and executed using Java interpreter ( java ).
The java debugger jdb is used to find errors if any.
A compiled Java program can be converted into source code with help of Java disassembler javap.
Documentation Section:
This section comprises set of comment lines giving name of the program, author and other details, which
programmer would like to refer at latter stage.
Comments must explain why and what of classes and how of algorithms.
Package Statement:
The first statement allowed in Java file is package statement.
This statement declares package name and informs compiler that classes defined here belong to this
package.
Example: package student;
Import Statements:
The next statement will be number of import statements. It is similar to #include statement.
Example: import student.text;
This statement instructs interpreter to load test class contained in package student.
Interface Statements:
An interface is like class but includes group of method declarations.
This is also an optional section and is used only when we wish to implement multiple inheritance
features.
Class Definitions:
Java program may contain multiple class definitions.
Classes are primary and essential element of Java program.
The number of classes used depends on complexity of problem.
Java Tokens
A Java program is basically collection of classes.
Class is defined by set of declaration statements and methods containing executable statements
Most statements contain expressions, which describe the actions carried out on data.
Smallest individual units in program are known as tokens.
There are 5 types of tokens:
o Reserved keywords
o Identifiers
o Literals
o Operators
o Seperators
Java Character Set
Smallest units of Java language are characters used to write Java tokens.
These characters are defined by Unicode character set.
The Unicode is 16-bit character coding system.
However we use only basic ASCII characters, which include letters, digits and punctuation marks.
Keywords
Keywords are an essential part of a language.
They implement specific features of the language.
Java has reserved 50 words as keywords.
Below table list few keywords:
abstract case continue byte
for import static final
new public if switch
do class while this
Since keywords have specific meaning in Java, we cannot use them as names for variables, classes, methods
and so on.
All keywords are written in lower-case letters
Identifiers
Identifiers are programmer-designed tokens.
They are used for naming classes, methods, variables, objects, labels, packages and interfaces in a program.
Java identifiers follow the following rules:
o They can have alphabets, digits and underscore and dollar sign characters.
o They must not begin with numbers.
o Uppercase and lowercase characters are distinct.
o They can be of any length.
Identifiers should be short and meaningful.
Literals
Literals in Java are a sequence of characters ( digits, letters and other characters) that represent constant
values to be stored in variables.
Java language specifies 5 types of literals. They are:
o Integer Literals
o Floating-point Literals
o Character Literals
o String Literals
o Boolean Literals
Operators
An operator is symbol that takes one or more arguments and operates on them to produce result.
Separators
Separators are symbols used to indicate where groups of code are divided and arranged.
They basically define function of our code.
Below table contains list of separators and their function:
Java Statements
The statements in Java are like sentences in natural languages.
A statement is an executable combination of tokes ending with a semicolon ( ; ).
Statements are executed in sequence in the order in which they appear.
It is possible to control flow of execution using special statement
Java Statements
Synchronization
Expression Statement
Statement Guarding
Labelled Statement
Statement Control
Statement
if switch
while for break continue
if-else do return
Now, interpreter looks for main method in program and begins execution from there.
When executed it will display the following:
Hello!
Welcome to the world of Java.
Machine Neutral
The compiler converts source code files into bytecode files.
These are machine-independent and therefore can be run on any computer.
Java interpreter reads bytecode files and translates them into machine code for specific machine on
which Java program is running.
This is illustrate in below figure:
Source Code
Java Compiler
Bytecode
Source Code
Real Machine
Operating System
Java Virtual Machine
Java Object Framework ( API )
Compiler Interpreter
User
Command Line Arguments
Command line arguments are parameters that are supplidto program at execution time.
We can write Java program that can receive and use arguments provided in command line.
Consider the line:
public static void main( String args[] )
Here args contains the array of values passed from command line arguments.
For example consider,
Java Test BASIC FORTRAN C++ JAVA
The values stored in args are as follows:
args[ 0 ] BASIC
args[ 1 ] FORTRAN
args[ 2 ] C++
args[ 3 ] JAVA
Programming Style
Java is a freefrom language.
Java system does not care where on the line we begin typing.
Several alternative styles are possible, from which any one can be selected.
For example,
System.out.println( “ Java is wonderful “);
Can be written as,
System.out.println
( “ Java is wonderful “);
Constants
Constants in Java refer to fixed values that do not change during the execution of program.
Integer Constants
An integer constant refers to sequence of digits. There are three types of constants:
o Decimal integer: constits of any combination set of digits from 0 to 9
Example: 789, -98, 3
o Octal integer: constits of any combination of digits from 0 to 7
Example: 037, 09
o Hexadecimal integer: constits of any combination of 0 to 9 and A to F
Example: 0X2, 0X5A
Real Constants
The floating values assigned to any variables are nothing but real constants.
Example: 0.890, 78.97
Real constants may also be expressed in exponential notation. General form is as follow:
mantissa e exponent
The mantissa is either real numbers or integer numbers, exponent is integer with + or – sign.
Example: 0.65e4, 12e-9
String Constants
A string constant is a sequence of characters enclosed between double quotes.
The character may be alphabet, digits, special character and blank spaces.
Example: “ Hello “, “hi 123” Constants Meaning
\b backspace
Backslash Character Constants \f form feed
Java supports some special backslash character constants that are \n new line
used in output methods. \t horizontal tab
The below table shows some of them: \’ single quote
\\ back slash
Variables
A variable is an identifier that denotes a storage location used to store a data value.
Variable may take different values at different times during execution of program.
A variable name can be choosen by programmer in meaning way so as to reflect wht it represents in the
program.
Some of the examples are:
average, height, total_height.
Variable may consist of alphabets, digits underscore( _ ), $ with following conditions:
o They must not begin with digit
o Uppercase and lowercase characters are distinct.
o It should not be keyword
o White spaces not allowed.
Data types
Data types specify the size and type of values that can be stored. Java is rich in its data types.
Data types in Java under various categories are shown below:
Interface
Integer Floating - Character Boolean
point
Integer types
It can hold numbers such as 123, -98 etc.
The following table shows the types on integer, its size and range available in Java
Type Size Minimum value Maximum value
byte 1 byte -128 127
short 2 bytes -32,768 32,767
int 4 bytes -2,147,483,648 2,147,483,647
long 8 bytes -9,223,372,036,854,775,808 9,223,372,036,854,775,807
Floating types
Floating point type holds numbers containing fractional parts such as 23.87, -9.67.
There are 2 types in floating point type:
Type Size Minimum value Maximum value
float 4 bytes 3.4e-038 1.7 e+0.38
double 8 bytes 3.4e-038 1.7e+308
Character types
In order to store character constants in memory, Java provides character data type called char.
The char type assumes size of 2 bytes, but basically holds only 1 character.
Boolean types
This is used when we want to test particular condition during execution of program.
It holds only 2 values either TRUE or FALSE.
Scope of variable
Java variables are actually classified into 3 kinds:
o Instance variable
o Class variable
o Local variable
Instance and class variables are declared inside class.
Instance variables are created when objects are instantiated and are associated with objects. They
take different values for each objects.
Class variables are global to class and belong to entire set of objects that class creates. One memory
location is created for each class variable.
Variables declared and used inside methods are called local variables.
The area of program where the variable is accessible is called its scope.
The scope of local variables is between the opening brace { and closing brace }
Symbolic Constants
The symbolic constants may appear repeatedly in number of places in program.
One example of such constant is 3.142 i.e PI value, another example is total number of students let it
be 50.
While using this we face 2 problems:
o Problem in modification of program.
o Problem in understanding the program
Modifiability
We may like to change the value of PI from 3.142 to 3.14159 to improve the accuracy of calculation or
the number 50 to 100.
In both the cases the values have to change wherever it is being used, if not then program may produce
disastrous outputs.
Understandability
When numeric value appears in program, it is not always clear, same number can be used in different
place in program.
For example 50 may mean number of students at one place and pass marks in another place.
So to overcome these problems we should declare variable as final and assign a constant value it as
follows:
final int STRENGTH = 100;
final int PASS_MARKS = 50;
final float PI – 3.14159;
Type casting
We often encounter situations where there is a need to store a value of one typeinto variable of
another type.
In such situations we must cast the value , its syntax is as follows:
Type variable1 = (type) variable2;
The process of converting one data type to another is called casting.
Example:
int m = 50;
byte n = (byte) m;
long count = (long) m;
Casting is often necessary when method return a type different than the one we require.
Casting into smaller may result into loss of data.
Automatic Conversion
It is possible to assign a value of one type to variable of different type without cast.
Java does the conversion of assigned value automatically. This is known as automatic type
conversion.
Automatic type conversion is possible only if destination type has enough precission to store source
value.
Example:
byte b = 75;
int a = b;
The process of assigning smaller type to larger one is known as widening or promotion, and that of
assigning larger type to smaller type is known as narrowing.
Type of Default value
Standard Default Values variable
In Java, every variable has a default value. byte 0
If we don’t initialize a variable when it is first created, Java provides short 0
int 0
default value to variable.
long 0L
The following tables specify some default values:
float 0.0f
double 0.0d
char null character
Special Operators Boolean false
Java supports some special operators of interest such as:
Instanceof Operator
The instanceof is an object reference operator and returns true if the object on left-hand side is an
instance of the class given on right-hand side.
This operator allows us to determine whether the object belongs to particular class or not.
Example:
Person instanceof student
Is true if object person belongs to class student; otherwise flase.
Dot Operator
The dot operator is used to access the instance variables and methods of class objects.
Example:
person1.age //References to variable age
person1.salary() //Reference to the method salary()
Mathematical Functions
Mathematical functions such as cos,sqrt, log etc are frequently used in analysis of real-life problems.
Java supports these basic mathfunctions through Math class defined in java.lang package.
The functions should be used as follows:
Math.function_name(); Functions Actions
sin(x) Returns sine of angle x in radians
The following table list the math functions cos(x) Returns cosine of angle x in radians
defined Math class: tan(x) Returns tangent of angle x in radians
pow(x,y) Returns x raised y ( xy )
exp(x) Returns e raised to x ( ex )
sqrt(x) Returns square root of x
max(a,b) Returns maximum of a and b
min(a,b) Returns minimum of a and b
log(x) Returns natural logarithm of x
Labeled Loops ( break and continue )
In Java, we can give a label to a block of statement. A label is any valid Java variable name.
To give label to a loop, place it before the loop with a colon at the end.
Example: Loop1: for( …………….. )
{
………………….
………………….
}
………………….
If we want to jump outside a nested loops or the continue loop that is outside the current one, then we have
to use labelled break and labelled continue stataments.
Example:
Outer: for(int m=1; m<11; m++)
{
for(int n=1; n<11; n++)
{
System.out.print(“ “ + m*n);
if ( n==m )
continue outer;
}
}
Here continue statement terminates inner loop when n=m and continues with next iteration of outer
loop.
Consider another example:
loop1: for(inti=0; i<10; i++ )
{
loop2: while ( x< 100 )
{
y = i * x;
if ( y> 500 )
break loop1;
………………..
}
……………………
}
……………………..
Here break loop1 causes the execution to break out of both the loops.
Java language provides 3 constructs for performing loop operations, they are:
1. while construct
2. do-while construct
3. for construct
CHAPTER 2
Introduction
Anything we wish to represent in a Java program must be encapsulated in a class that defines the state
and behavior of the basic program components known as objects.
Classes create objects and objects use methods to communicate between them.
Classes provide a convenient method for packing together a group of logically related data items and
functions that work on them.
In Java, the data items are fields and functions are called methods.
A class is essentially a description of how to make an object that contains fields and methods.
Defining a class
A class is a user-defined data type with a template that serves to define its properties.
Once the class type has been defined, we create “variables” of that type using declarations that are
similar to the basic type declaration.
In Java, these variables and termed as instances of classes, which are the actual objects.
The basic form of a class definition is:
classclassname [ extendssuperclassname]
{
[ fields declaration; ]
[ methods declaration; ]
}
Classname and superclassname are any valid Java identifiers.
The keyword extends indicates that the properties of superclassname class are extended to classname
class.
Fields declaration
Data is encapsulated in a class by placing data fields inside the body of class definition.
These variables are called instance variables because they are created whenever an object of a class is
instantiated. Also called as member variables.
We can declare the instance variables exactly the same way as we declare local variables.
Example:
class Rectangle
{
int width;
int length;
}
These variables are only declared and therefore no storage space has been created in memory.
Methods declaration
A class with only data fields has no life. Objects created by such class cannot respond.
Adding of methods is necessary for manipulating the data contained in the class.
Methods are declared inside body of class but immediately after declaration of variables.
The general form of method declaration is as follows:
typemethodname ( parameter_list )
{
Method-body;
}
Method declaration have four basic parts:
o Name of method ( methodname )
o Type of value the method returns ( type )
o List of parameters ( parameter_list )
o Body of method.
The type specifies the type of value the method would return. This could be simple data type such as
int or any class type, or even void i.e will not return anything.
The parameter list is always enclosed in parentheses. This contains variable name and types of all
values we want to give to method as input, separated by commas.
The body actually describes the operations to be performed on the data.
Consider the below given example:
class Rectangle
{
int length, width;
void getdata(int x, int y)
{
length = x;
width = y;
}
int rectArea()
{
int area = length * width;
return area;
}
}
Creating objects
An object in Java is essentially a block of memory that contains space to store all instance variables.
Creating of objects is also referred to as instantiating an object.
Objects are created using new operator.
The new operator creates an object of the specified class and returns reference to that object.
Here is an example of creating an object type of Rectangle:
Rectangle rect1;
rect1 = new Rectangle ( );
The first statement declares variable to hold object reference and second one actually assigns object
reference to the variable.
The variable rect1 is now an object of Rectangle class. It is showed in below figure:
Action Statement Result
Rectangle
rect2
object
Method Overloading
In Java, it is possible to create methods that have the same name, but different parameter lists and
different definitions. This is called method overloading.
Method overloading is used when objects are required to perform similar tasks but using different
input parameters.
When we call method in an object, Java matches up the method name first and then the number and
type of parameters to decide which one of definitions to execute. This is polymorphism.
To create an overloaded method, all we have to do is to provide several different method definitions in
class, all with same name, but with different parameters lists.
The difference may be either be in the number or type of arguments.
Static Members
A class basically contains two sections: One declares variables and other declares methods.
These variables and methods are called instance variables and methods.
This is because everytime the class in instantiated a new copy of each of them is created.
They are accessed using objects with dot operator.
Let us assume that we want to define a member that is common to all objects and accessed without
using a particular object.
That is, the member belongs to class as a whole rather than the object created.
Such members can be defined as follows:
static int count;
static int max ( int x, int y );
The members that are declared static are called as static members.
Since these members are associated with the class itself rather than individual objects, the static
variables and static methods are often referred to as class variables and class methods.
Static variables are used when we want to have variable common to all instance of a class.
Static methods can be called without using the objects.
Java class libraries contain large number of class methods.
For example, Math class of Java library defines many static methods to perform math operations like:
float x = Math.sqrt(25.0);
The static members are called using class names, no objects will be created.
Static methods have several restrictions:
o They can only call other static methods.
o They can only access static data.
o They cannot refer to this or super.
Below program illustrate this:
class MathOperation
{
int m, n;
Nesting ( int x, int y )
{
m = x;
n = y;
}
int largest( )
{
if ( m >= n )
return ( m );
else
return ( n );
}
void display( )
{
int large = largest ( );
System.out.println( “ largest value + “ + large );
}
}
class NestingTest
{
public static void main ( String args [ ] )
{
Nesting nest = new Nesting ( 50, 40 );
nest.display( );
}
}
The class Nesting defines one constructor and two methods, namely larget() and display().
The method display() calls the method largest() to determine the largest of two numbers and then
display the result.
A A A A B
B
B D C
B
(a) (b) (c) (d)
Java does not directly implement multiple inheritance, it is done using interfaces.
Defining a Subclass
A sub class is defined as follows:
class subclassname extends superclassname
{
variables declaration;
methods declaration;
}
The keyword extends signifies that the properties of superclassname are extended to the subclassname.
Subclass Constructor
It is used to construct the instance variables of both subclass and superclass.
The subclass constructor uses keyword super to invoke the constructor method of superclass.
The keyword super is used subject to the following conditions:
o Super may only be used within subclass constructor method.
o The class to superclass constructor must appear as first statement in subclass constructor.
o The parameter in super call must match the order and type of instance variable declared in
superclass.
Below program illustrates the concept of Single inheritance:
class Room
{
int length, breadth;
Room ( int x, int y )
{
length = x;
breadth = y;
}
int area ( )
{
return ( length * breadth );
}
}
class BedRoom extends Room // Inheriting Room
{
int height;
BedRoom ( int x, int y , int z )
{
super( x, y ); // Pass values to supercalss
height = z;
}
int volume ( )
{
return ( length * breadth * height );
}
}
class InherTest
{
public static void main ( String args [ ] )
{
BedRoom room1 = new BedRoom( 14, 12, 10 );
int area1 = room1.area( );
int volume1 = room1.volume( );
System.out.println(“ Area = “ + area1 );
System.out.println(“ Volume = “ + volume1 );
}
}
Multilevel Inheritance
A common requirement in object-oriented programming is the use of derived class as a super class.
Java supports this concept and uses it extensively in building its class library.
This concept allows us to build a chain of classes as shown in figure: A
The class A server as base class for derived class B which in turn serveras base
class for derived class C. This chain ABC is known as Inheritance path. B
A derived class with multilevel base classes is declared as follows:
Class A
{ C
...........
...........
}
Class B extends A
{
...........
...........
}
Class C extends B
{
...........
...........
}
Hierarchical Inheritance
Many programming problems can be cast into hierarchy when certain features of one level are shared
by many others below the level.
As an example, below figure shows a hierarchical classification of accounts in a commercial bank.This
is possible because all accounts possess certain common features.
Account
Short Long
Medium
Overriding Methods
There may be occasions when we want an object to respond to the same method but have different
behavior when that method is called.
That means, we should override the method defined in superclass.
This is possible by defining a method in the subclass that has same name, same arguments and same
return type as method in superclass.
When the method is called the method defined in subclass is invoked and executed instead of the one
in superclass.
Below program illustrates the concept of overriding. The method display() is overriden.
class Super
{
int x;
Super (int x)
{
this.x = x;
}
void display()
{
System.out.println(“Super x = “ + x );
}
}
class Sub extends Super
{
int y;
Sub (int x, int y)
{
super ( x );
this.x = x;
}
void display()
{
System.out.println(“Super x = “ + x );
System.out.println(“Sub y = “ + y );
}
}
class OverrideTest
{
public static void main ( String args [ ] )
{
Sub s1 = new Sub( 100, 200 );
s1.display( );
}
}
Final Classes
Sometimes we may like to prevent class being further subclasses for security reasons.
A class that cannot be subclassed in called final class.
This is achieved in Java using the keyword final as follows:
final class A { . . . . . . . }
Any attempt to inherit these classes will cause an error and complier will not allow it.
Declaring a class final prevents any unwanted extensions to the class.
Finalizer Methods
Constructor method is used to initialize an object when it is declared, this is initialization.
Java supports a concept classed finalization, which is just opposite to initialization.
Java run-time is an automatic garbage collection system.
It automatically frees up the memory resources used by the objects.
But objects may hold other non-object resources such as file descriptors or window system fonts. The
garbage collector cannot free these resources.
In order to free these resources we must use a finalizer method.
The finalizer method is simply finalize( ) and can be added to any class.
Java calls that method whenever it is about to reclaim the space for that object.
The finalize method should explicitly define the tasks to be performed.
Example:
abstract class Shape
{
.............
abstract void draw ( );
.............
}
When class contains one or more abstract methods, it should also be declared abstract.
While using abstract classes, we must satisfy the following conditions:
o We cannot use abstract classes to instantiate objects directly. For example:
Shape s = new Shape ( );
is illegal because shape is an abstract class.
o The abstract methods of an abstract class must be defined in its subclass.
o We cannot declare abstract constructors or abstract static methods.
Varargs allows us to declare method with unspecified number of parameters for given argument.
The varargs must be the final argument in argument list of method.
Varargs is identified by type of an argument followed by ellipsis ( . . . ) & name of variable.
Below program illustrates varargs
Class Exampleprg
{
Exampleprg ( String . . . person )
{
for( String name: person )
{
System.out.println(“ Hello “ + name );
}
}
public static void main ( String args [ ] )
{
Exampleprg(“ABC”, “CDE”, “FGH”, “IJK”);
}
}
In above program A.method ( ) call invokes the Sub class version and not of Super class
irrespective of the fact that A is Super type variable.
Thus in dynamic method dispatch the type of reference variable is irrelevant while choosing
particular version of overridden method for invocation; instead it soley depends on type of object being
referred by reference variable.
Visibility Control
It may be necessary in some situations to restrict the access to certain variables and methods from
outside the class. The visibility modifiers are also known as access modifiers.
For example, we may not like objects of class directly alter value of variable or access method.
We can achieve this in Java by applying visibility modifiers to instance variables and methods.
Java provides three types of visibility modifiers: public, private and protected.
public Access
Any variable or method is visible to entire class in which it is defined.
A variable or method declared as public has widest possible visibility and accessible everywhere.
Example:
public int number;
public void Sum ( ) { . . . . . . . . . . . }
friendly Access
when no access modifier is specified, member defaults to limited version of accessibility known as “
friendly “ level of access.
Friendly access makes fields visible only in the same package, but not in other packages.
protected Access
The visibility level of “protected” field lies in between public and friendly access.
The protected modifier makes the field visible not only to all classes and subclasses in same package
but also to subclasses in other packages.
private Access
The private fields enjoy the highest degree of protection. They are accessible only with their own
class.
They cannot be inherited by subclasses and therefore not accessible in subclasses.
Method declared as private behaves like method declared as final.
Strings
Strings represent a sequence of characters.
The easiest way to represent a sequence of character in Java is by using a character array.
Example:
char charArray[ ] = new char[4];
charArray[0] = ‘ a ‘;
charArray[1] = ‘ T ‘;
charArray[2] = ‘ S ‘;
charArray[3] = ‘ g ‘;
In Java, strings are class objects and implemented using two classes namely: String and StringBuffer.A
Java string is an instantiated object of the String class.
Java strings, as compared to C strings are more reliable and predictable.
Java string is not a character array and is not NULL terminated.
It may be declared as follows:
String stringName;
stringName = new String (“ string “);
It can also be written as:
String firstName = new String(“ Preetam “);
String can be concatenated using + operator as follows:
String Arrays
We can also create and use arrays that contain string.
The statement
String itemArray[ ] = new String [ 3 ];
will create an itemArray of size 3 to hold three string constants.
We can assign the strings to the itemArray element by element using three different statements or by
using for loop.
String Methods
The String class defines a number of methods that allow us to accomplish a variety of string
manipulation tasks.
Below table lists some of the most commonly used methods and their tasks.
StringBuffer Class
StringBuffer is a peer class of String.
While String creates strings of fixed_lenth, StringBuffer creates strings of flexible length that can be
modified in terms of both length and content.
We can insert characters and substrings in the middle of a string, or append another string to the end.
Below table shows some of the methods that are frequently used in string manipulation:
Method Task
s1.setCharAt( n, ‘x’ ) Modifies the nth character to x
s1.append ( s2 ) Appends the string s2 to s2 at the end
s1.insert ( n, s2 ) Inserts string s2 at the position n of the string s1
s1.setLength ( n ) Sets the length of string s1. If n < s1.length( ) s1 is truncated. If n >
s1.length zeros are added to s1
Vectors
Vector class is contained in java.util package.
This class can be used to create a generic dynamic array known as vector that can hold objects of any
type and any number.
The object do not have to be homogeneous.
Arrays can be easily implemented as vectors.
Vectors are created as follows:
Vector intVect = new Vector( );
Vector list = new Vector( 3 );
Vector can be declared without specifying any size explicitly.
It can accommodate an unknown number of items.
Vector posses a number of advantages over arrays:
o It is convenient to use vectors to store objects.
o Vector can be used to store list of objects that may vary in size.
o We can add and delete objects from the list as and when required.
A major constraint in using vectors is that we cannot directly store simple data type in a vector; we can
only store objects.
Therefore, we need to convert simple types to objects. This can be done using the wrapper classes.
The vector class supports number of methods that can be used to manipulate the vectors created.
Below tables shows some of them:
Method Call Task performed
list.addElement ( item ) Adds item specified to the list at the end
list.elementAt ( 10 ) Gives the name of the 10th object
list.size( ) Gives the number of object present
list.removeElement ( item ) Removes specified item from list
list.removeElementAt ( n ) Removes item stored in nth position in list
list.removeAllElements( ) Removes all the element in the list
list.copyInto ( array ) Copies all items from list to array
list.insertElementAt ( item, n ) Inserts the item at nth position
try
{
DataInputStream in = new DataInputStream( System.in );
System.out.print(“Enter Principle Amount: “);
System.out.flush( );
String principalString = in.readLine( );
principalAmount = Float.valueOf( principalString );
}
}
Enumerators
J2SE 5.0 allows us to use the enumerated type in Java using enum keyword.
This keyword can be used similar to static final constants.
For example, consider the following code:
Public class Days
{
public static final int DAY_SUNDAY = 0;
public static final int DAY_MONDAY = 1;
public static final int DAY_TUESDAY = 2;
public static final int DAY_WEDNESDAY = 3;
public static final int DAY_THURSDAY = 4;
public static final int DAY_FRIDAY = 5
public static final int DAY_SATURDAY = 6;
}
Using the enumerated type feature provided by J2SE 5.0, the above code can be rewritten as:
Public enum Day { SUNDAY, MONDAY, T UESDAY, WEDNESDAY, THURSDAY, FRIDAY,
SATURDAY };
The advantages of using the enumerated type are:
Compile-time type safety
We can use the enum keyword in switch statements.
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY
};
Annotations
The annotations feature, introduced by J2SE 5.0 is also known as metadata.
We can use this feature to merge additional Java elements with the programming elements, such as
classes, methods, parameters, local variables, packages and fields.
Metadata is stored in Java class files by compiler and these class files are used by JVM or by program
to find the metadata for interacting with programming elements.
Java contains the following standard annotations:
Annotation Purpose
@Deprecated Compiler warns when deprecated java elements are used in non-deprecated program
@Overrides Compiler generated error when the method uses this annotation type does not override
methods present in super-class
In addition to the above standard annotations, Java also contains some meta-annotations available in
the java.lang.annotation package.
The following table provides the meta-annotations:
Meta-annotation Purpose
@Documented Indicates annotation of this type to be documented by Javadoc
@Inherited Indicates that this type is automatically inherited
@Retention Indicates the extended period using annotation type.
@Target Indicates to which program element the annotation is applicable
For example, consider the following code that contains declaration of annotation:
Package njunit.annotation;
Import java.lang.annotation.*;
@Retention( Retentionpolicy.RUNTIME )
@Target((ElementType.METHOD))
Public @interface UnitTest
{
String value ( );
}
@Retention is meta-annotation, which declares that the @UnitTest annotation must be stored in class
file.
The @Target meta-annotation is used to declare @UnitTest annotation, which annotates the methods
in Java class files.
The @interface meta-annotation is used to declare @UnitTest annotation with member called value,
which returns String as an object.
CHAPTER 3
INTERFACES: MULTIPLE INHERITANCE
Introduction
Java cannot have more than one superclass.
For instance, a definition like:
class A extends B extends C
{
............
............
}
is not permitted in Java.
Java provides an alternate approach known as interfaces to support the concept of multiple inheritance.
Although a Java class cannot be a subclasss of more than one superclass, it can implement more than
one interface, thereby enabling us to create classes that build upon other classes without the problems
created by multiple inheritance.
Defining Interfaces
An interface is basically a kind of class.
Like classes, interfaces contain methods and variables but with major difference.
The difference is that interfaces define only abstract method and final fields.
This means that interfaces do not specify any code to implement these methods and data fields contain
only constants.
Therefore, it is the responsibility of the class that implements an interface to define the code for
implementation of these methods.
The syntax for defining an interface is very similar to that for defining class.
The general form of an interface definition is:
interface interfaceName
{
variable declaration
methods declaration
}
Here, interface is the keyword and interfaceName is an valid Java variable.
Variables will be declared as constants as follows:
static final type variableName = value;
Methods declaration will contain only a list of methods without any body statements.
Exmaple:
return_type methodName ( parameter_list );
Here is an example of an interface definition:
interface Item
{
Extending Interfaces
Like classes, interfaces can also be extended i.e interface can be subinterfaces from other interface.
The new subinterface will inherit all the members of superinterface.
This is achieved using keyword extends as shown below:
interface name2 extends name1
{
body of name2
}
For example, we can put all constants in one interface and methods in another, as shown below:
interface ItemConstants
{
int code = 1001;
String name = “Fan”;
}
interface Item extends ItemConstants
{
void display( );
}
The interface Item would inherit both the constant code and name into it.
We can also combine several interfaces together into single interface.
Sub interfaces cannot define the methods declared in the super interfaces.
It is the responsibility of any class that implements derived interface to define all the methods.
Implementing Interfaces
Interfaces are used as “superclasses” whose propertied are inherited by classes.
It is therefore necessary to create class that inherits give interface.
This is done as follows:
class classname implements interfacename
{
Body of classname
}
Class B Class B E
Extension Extension Implementation Implementation
B C
Class C Class C
Interface A Interface B
Extension
C Interface
(d) Implementation
D Class
{
return ( pi * x * y );
}
}
class InterfaceTest
{
public static void main ( String args[ ] )
{
Rectangle rect = new Rectangle( );
Circle cir = new Circle ( );
Area area;
area = rect;
System.out.println(“Area of Rectangle = “ + area.compute(10,20) );
area = cir;
System.out.println(“Area of Circle = “ + area.compute(10,0) );
}
}
Below program illustrates the implementation of the concept of multiple inheritance using interfaces.
class Student
{
int rollNumber;
void getNumber ( int n )
{
rollNumber = n;
}
void putNumber( )
{
System.out.println(“ Roll No: “ + rollNumber );
}
}
class Test extends Student
{
float part1, part2;
void getMarks( float m1, float m2 )
{
part1 = m1;
part2 = m2;
}
void putMarks( )
{
System.out.println(“ Marks obtained are: “);
System.out.println(“ Part1: “ + part1);
System.out.println(“ Part2: “ + part2);
}
}
interface Sports
{
float sportWt = 6.0F;
void putWt( );
}
class Results extends Test implements Sports
{
float total;
public void putWt( )
{
System.out.printlm(“Sports Wt = “ + sportWt);
}
void display( )
{
total = part1 + part2 + sportWt;
putNumber( );
putMarks( );
putWt( );
System.out.println(“ Total score = “ + total );
}
}
class Hybrid
{
publicstatic void main( String args [ ] )
{
Results student1 = new Results ( );
student1.getNumbers(1234);
student1.getMarks(27.5F, 33.0F);
student1.display();
}
}
The Output of above program:
Roll No: 1234
Marks obtained:
Part1 = 27.5
Part2 = 33
Sports Wt = 6
Total score = 66.5
Chapter 4
Packages: Putting Classes Together
Introduction
Packages are Java’s way of grouping a variety of classes and/or interfaces together.
The grouping is usually done according to functionality.
Packages act as “containers” for classes.
By organizing our classes into packages we achieve the following benefits:
o The classes container in the packages of other programs can be easily reused.
o In packages, classes can be unique compared with classes in other packages. i.e two classes in two
different packages can have same name.
o Packages provide a way to “hide” classes thus preventing other programs or packages from
accessing classes that are meant for internal use only.
o Packages provide a way for separating “design” and “coding”.
We can build our own classes for handling our data and use existing class libraries for designing user
interfaces.
Java packages are therefore classified into two types i.e Java API packages and User Defined
packages.
Java
lang applet
util net
io awt
Graphics
Package containing classes
Font
Image Classes containing methods
This shows that package named java contains the package awt, which inturn contains various classes
required for implementing graphical user interface.
There are two ways of accessing the classes stored in a package.
The first approach is to use the fully qualified class name of class that we want to use.
This is done by using the package name containing class and then appending class name to it using dor
operator.
For example, if we want to refer to class Color in awt package, then it is done as follows:
java.awt.Color
This approach is perhaps the best and easiest one if we need to access the class only once or when we
need not have to access any other classes of the package.
Sometimes we might want to use a class in number of places in program or we may like to use many
of classes contained in package.
We achieve this as follows:
import packagename.classname
import packagename.*
These are known as import statements and must appear at the top of file, before any class declaration,
import is a keyword.
Naming Conventions
Packages can be named using the standard Java naming rules i.e packages begin with lowercase letters.
This makes it easy for users to distinguish package names from class names when looking at an
explicit reference to class.
For example,
double y = java.lang.Math.sqrt(x);
Creating Packages
To create our own package we must first declare the name of the package using package keyword
followed by package name.
This must be the first line in Java source file, then we define class.
For example,
package firstPackage;
public class FirstClass
{
...........
...........
}
Here package name is firstPackage, the class FirstClass is now considered part of this package.
This would be saved as file called FirstClass.java, and located in directory named firstPackage.
When source file is compiled, Java will create .class file and store in same directory.
Steps followed to create our package involves following steps:
1. Declare package at the beginning of file using the form:
package packagename;
2. Define the class that is to be put in package and declare it public.
3. Create a subdirectory under the directory where the main source files are stored.
4. Store the listing as classname.java file in subdirectory created.
5. Compile the file. This creates .class file in subdirectory.
Java also supports the concept of package hierarchy.
This is done by specifying multiple names in package statement, separated by dots.
For example,
package firstPackage.secondPackage;
Accessing a Package
We use the import statement when there are many references to a particular package or package name
is too long and unwieldy.
The same import statements can be used to access user-defined packages.
The general form of import statement is as follows:
import package1 [.package2] [.package3] .classname;
Here package1 is the name of the top level package, package2 is name of package that is inside
package1 and so on.
We can have any number of packages in package hierarchy followed by classname.
Multiple import statements are allowed and should end with semicolon ( ; ).
Example:
import firstPackage.secondPackage.MyClass;
After defining this statement, all members of class MyClass can be directly accessed using class name
or its objects directly without using package name.
We can also write as:
import packagename.*;
The major drawback of shortcut approach is that it is difficult to determine from which package a
particular member came.
The advantage is that we need not have to sue long package names repeatedly in program.
Using a Package
The listing below shows a package named package1 containing single class ClassA.
package package1;
public class ClassA
{
public void displayA( )
{
System.out.println(“Class A”);
}
}
This source file should be named ClassA.java and stored in subdirectory package1.
Compile the file and resultant ClassA.class will be stored in same directory.
This listing shows simple program that imports ClassA from package1.
The source file should be saved as PackageTest1.java and then compiled.
The source file and compiled file would be saved in directory of which package1 was subdirectory.
Now we can run the program.
During the compilation of PackageTest1.java the compiler checks for the file ClassA.class in package1
directory for information it need, but it does not actually include the code from ClassA.class in file
PackageTest1.class.
When PackageTest1 program is rum, Java looks for file PackageTest1.class and loads it using
something called class loader.
Now interpreter knows that it also need code in file ClassA.class and loads it as well.
Consider another package named package2 containing single class as shown below:
package package2;
public class ClassB
{
protected int m =10;
public void display( )
{
System.out.println(“Class B”);
System.out.println(“ M = “ + m );
}
}
We can have a sub class of the imported class from package. It is as shown below:
import package1.ClassA;
import package2.ClassB;
class classC extends ClassB
{
int n = 20;
void display( )
{
System.out.println(“Class C”);
System.out.println(“M = “ + m);
System.out.println(“N = “ + n);
}
}
class PackageTest2
{
public static void main( String args [ ] )
{
ClassA objectA = new ClassA( );
ClassC objectC = new ClassC( );
objectA.displayA( );
objectC.displayB( );
objectC.displayC( );
}
}
When we import multiple packages it is likely that two or more packages contain classes with identical
names.
Example:
package pack1;
public class Teacher
{ ............ }
public class Student
{ ............ }
package pack2;
public class Courses
{ ............ }
public class Student
{ ............ }
We can import both the packages like this:
import pack1.*;
import pack2.*;
Student student1;
Since both the packages contain class Student, compiler cannot understand which one to use and
therefore generates an error.
This problem can be overcome as follows:
import pack1.*;
import pack2.*;
pack1.Student student1;
pack2.Student student2;
The access protection detains for packages is as given in below table:
Access modifier
Access location public protected friendly private protected private
Same class Yes Yes Yes Yes Yes
Subclass in same package Yes Yes Yes Yes No
Other classes in same package Yes Yes Yes No No
Subclass in other packages Yes Yes No Yes No
Non-subclasses in other package Yes No No No No
4. Compile ClassB.java file. This will create ClassB.class file and place it in p1
Now package p1 will contain both the class ClassA and ClassB.
Statement like import p1.* will import both the classes.
If we want to create package with multiple public classes in it, we follow the following steps:
1. Decide the name of the package.
2. Create a subdirectory with this name under the directory where main source files are stored.
3. Create classes that are to be placed in package in separate source files and declare package
statement
package packagename
At the top of each source file
4. Switch to the subdirectory created earlier and compile each source file. When completed, package
would contain .class files for all the source files.
Hiding Classes
When we import package using asterisk ( * ), all public classes are imported.
However we may prefer to ‘not import’ certain classes i.e we may like to hide these classes from
accessing outside of packages.
Such classes should be declared “not public”.
Example:
package p1;
public class X
{
//body
}
class Y
{
//body
}
Here class Y is not declared public and is hidden from outside of package p1.
This class can be seen and used only by other classes in same package.
Consider the following code, which imports package p1:
Import p1.*;
X objectX; //OK; class X is available
Y objectY; //Not OK; Y is not available
Static Import
Static import is another feature introduced with J2SE 5.0 release.
This eliminates the need of qualifying static member with class name.
The static import declaration is similar to that of import.
Static import statements are used to import static members from classes and use them without
qualifying the class name.
They syntax is as follows:
import static package_name . subpackage_name . class_name . staticmember_name;
import static package_name . subpackage_name . class_name . *
Without using static import the static member PI from Math class was accessed as follows:
double area = Math.PI * radius * radius;
The following code provides an example of importing the interface into class.
The interface declared is as follows:
public interface Salary_increment
{
public static final double Manager = 0.5;
public static final double Clerk = 0.25;
}
This interface is present in the sub-package employee_details of employee package.
If we need to access the interface, we can import the interface using static import statements as
follows:
import static employee. Employee_details. Salary_increment;
Class Salary_hike
{
CHAPTER 5
MULTITHREADED PROGRAMMING
Introduction
Multithreading is a conceptual programming paradigm where a program is divided into two or more
subprograms ( processes ), which can be implemented at the same time in parallel.
For example, one sub program can display an animation on screen while another may build next
animation to be displayed.
This is something similar to dividing task into subtasks and assigning them to different people for
execution independently and simultaneously.
A thread is similar to program that has single flow of control. It has a beginning, a body and an end
and executes commands sequentially.
All main programs are called single-threaded programs.
Every program will have atleast one thread as shown in below figure:
Main Thread
.......
Main method
....... module
.......
A unique property of Java is its support for multithreading i.e Java enables us to use multiple flows of
control in developing programs.
Each flow of control may be thought of as separate tiny program known as thread that runs in parallel
to others as shown in figure.
A program that contains multiple flow of control is known as multithread program.
The above figure illustrates 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 other
threads namely A, B and C.
Once initiated by 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.
Since threads in Java are subprograms of main application program and share the same memory space,
they are known as lightweight threads or lightweight processes.
It is important to known that ‘threads running in parallel’ does not really mean that they actually run at
same time.
Since all threads are running on single processor, flow of execution is shared between threads.
The Java interpreter handles the switching of control between the threads in such a way that it appears
they are running concurrently.
Creating Threads
Creating threads in Java is easy.
Threads are implemented in the form of objects that contains method called run( ).
The run( ) method is the heart and soul of any thread.
It makes up the entire body of thread and is the only method in which the thread’s behavior can be
implemented.
A typical run( )would appear as follows:
public void run ( )
{
................
. . . . . . . . . . . . . . . . ( statements for implementing threads )
}
The run ( ) method should be invoked by an object of the concerned thread.
This can be achieved by creating thread and initiating it with help of another thread method called start ( ).
A new thread can be created in two ways:
1. By creating a thread class: Define a class that extends Thread class and override its run( ) method
with the code required by the thread.
2. 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 method with the code to be
executed by the thread.
................
}
Now we have a new type of thread MyThread.
Implementing the run( ) Method
The run( ) method has been inherited by the class MyThread.
We have to override this method in order to implement code to be executed by our thread.
The basic implementation of run() will look like this:
public void run( )
{
................
................
}
When we start the new thread, Java calls the thread’s run( ) method, so it is the run( ) where all the
action takes place.
Starting New Thread
To actually create and run an instance of our thread class, we write the following:
MyThread aThread = new MyThread( );
aThread.start( );
The first line instantiates or creates a new object of class MyThread.
The thread that will run this object is not yet running. It is just in newborn state.
The second line calls the start( ) method causing thread to move into runnable state.
Then, Java runtime will schedule thread to run by invoking its run( ) method.
Now, the thread is said to be in running state.
An Example of Using the Thread Class
The below Program illustrates the use of Thread class for creating and running threads in an
application.
The program creates 3 threads for three different tasks by writing below line:
new A( ).start( );
The main thread in ThreadTest class also constitutes another thread which may call “main thread”
class A extends Thread
{
public void run( )
{
for ( int i = 1; i<=5; i++)
{
System.out.println(“From ThreadA : 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(“From ThreadB : 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(“From ThreadC : k = “ + k );
}
System.out.println(“ Exit from C ”);
}
}
class ThreadTest
{
public static void main( String args[ ] )
{
new A( ).start( );
new B( ).start( );
new C( ).start( );
}
}
Blocking a Thread
A thread can also be temporarily suspended or blocked from entering into the runnable and
subsequently running state by using either of the following thread methods:
sleep ( ) suspend ( ) wait ( )
These methods cause the thread to go into the blocked or not-runnable state.
The thread will return to the runnable state when the specified time is elapsed in the case of sleep( ),
the resume( ) method is invoked in the case of suspend( ), and notify( ) method is called in the case of
wait( ).
3. Running state
4. Blocked state
5. Dead state
A thread is always in one of these five states. It can move from one state to another via a varity of
ways as shown in below figure:
New Thread
Newborn
stop
suspend resume
sleep notify stop
wait
Newborn state
When we create a thread object, the thread is born and is said to be in
newborn state. Newborn
The thread is not yet scheduled for running. At this state, we can do
only one of the following things with it: start stop
o Schedule it for running using start( ) method.
o Kill it using stop( ) method.
Runnable Dead
If scheduled, it moves to the runnable state as shown in figure: state state
If we attempt to use any other method at this stage, an exception
will be thrown.
Runnable state
The runnablestate means that the thread is ready for execution and is waiting for availability of the
processor.
That is, the thread has joined the queue of threads that are waiting for execution.
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.
The thread that relinquishes control joins the queue at the end and again waits for its turn.
This process of assigning time to threads is known as time-slicing.
If we want a thread to relinquish control to another thread to equal priority before its turn comes, we
can do so by using the yield( ) method as shown in below figure:
yield
Running state
Running means that the processor has given its time to the thread for its execution.
Tread runs until it relinquishes control on its own or it is preempted by higher priority thread
A running thread may relinquish its control in one of the following situations:
1. It has been suspended using suspend( ) method. A suspended thread can be revieved by using the
resume( ) method. This approach is useful when we want to suspend a thread for some time due to
certain reason, but do not want to kill.
suspend
resume
2. It has been made to sleep. We can put a thread to sleep for a specified time period using the method
sleep ( time ) where timeis in miliseconds. 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 )
3. It has been told to wait until some events occur. This is done using the wait( ) method. The thread
can be scheduled to run again using the notify( ) method.
wait
notify
Blocked state
A thread is said to be blocked when it is prevented from entering into the runnable state and
subsequently the running state.
This happens when the thread is suspended, sleeping, or waiting in order to satisfy certain
requirements.
A blocked thread is considered “not runnable” but not dead and therefore fully qualified to run again.
Dead state
Ever thread has a life cycle.
A running thread ends its life when it has completed executing its run( ) method.
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.
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.
}
System.out.println(“Exit from c”);
}
}
class ThreadDemo
{
public static void main(String args[ ] )
{
A threadA = new A ( );
B threadB = new B ( );
C threadC = new C ( );
Thread Exceptions
The sleep( ) method is enclosed in a try block and followed by catch block.
This is necessary because the sleep( ) method throws an exception, which should be caught.
If we fail to catch the exception, program will not compile.
Java run system will throw IllagalThreadStateException whenever we attempt to invoke method that a
thread cannot handle in given state.
For example, a sleeping thread cannot deal with resume( ) method because a sleeping thread cannot
receive any instructions.
The same is true with suspend( ) method when it is on a blocked thread.
Whenever we call a thread method that is likely to throw an exception, we have to supply an
appropriate exception handler to catch it.
The catch statement may take one of the following forms:
catch ( ThreadDeath e )
{
............
. . . . . . . . . . . . // Killed thread
}
catch ( InterruptedException e )
{
............
. . . . . . . . . . . . // cannot handle it in current state
}
catch ( IllegalArgumentException e )
{
............
. . . . . . . . . . . . // Illegal method argument
}
catch ( Exception e )
{
............
. . . . . . . . . . . . // Any other
}
Thread Priority
In Java, each thread is assigned a priority, which affects the order in which it is scheduled for running.
The threads of the same priority are given equal treatment by the Java scheduler and therefore, they
share the processor on a first-come, first-serve basis.
Java permits us to set the priority of a thread using the setPriority( ) method as follows:
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.
Default setting is NORM_PRIORITY
By assigning priorities to threads, we can ensure that they are given the attention they deserve.
For example, we may need to answer an input as quickly as possible.
Whenever multiple threads are ready for execution, the Java system chooses the highest priority thread
and executes it.
For a thread of lower priority to gain control, one of the following things should happen:
1. It stops running at the end of run( )
2. It is made to sleep using sleep( )
3. It is told to wait using wait( )
However, if another thread of higher priority comes along, the currently running thread will be
preempted by the incoming thread thus forcing the current thread to move to runnable state.
Highest priority thread always preempts any lower priority threads.
Below program illustrate the effect of assigning higher priority to thread.
class A extends Thread
{
public void run( )
{
System.out.println(“ ThreadA started “);
for( int i = 1; i <= 4 ; i++ )
System.out.println(“ From Thread A : i = “ +i );
System.out.println(“ Exit form A “);
}
}
class B extends Thread
{
Synchronization
One thread may try to read a record from a file while another is still writing to the same file.
Depending on the situation, we may get strange results.
Java enables us to overcome this problem using a technique known as synchronization.
In case of Java, the keyword synchronized helps to solve such problems by keeping a watch on such
locations.
For example, the method that will read information from a file and the method that will update the same
file may be declared as synchronized.
Example:
synchronized void update ( )
{
................
................ // code here is synchronized
}
When we declare a method synchronized, Java creates a “monitor” and hands it over to the thread that
calls method first time.
As long as the thread holds the monitor, no other thread can enter the synchronized section code.
A monitor is like a key and the thread that holds the key can only open the lock.
It is possible to mark a block of code as synchronized as shown below:
synchronized ( lock-object )
{
................
................ // code here is synchronized
}
An interesting situation may occur when two or more threads are waiting to gain control of resource.
Due to some reasons, the condition on which the waiting threads rely on to gain control does not
happen.
This results in what is known as deadlock.
For example, assume that the thread A must access Method1 before it can release Method2, but the
thread B cannot release Method1 until it gets hold of Method2.
Because these are mutually exclusive conditions, a deadlock occurs.
The code below illustrates this:
Thread A
synchronized Method2 ( )
{
synchronized Method1 ( )
{
................
................
}
}
Thread B
synchronized Method1 ( )
{
synchronized Method2 ( )
{
................
................
}
}
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 as implementing the Runnable interface.
2. Implement the run ( ) method.
3. Create a thread by defining an object that is instantiated from this “ runnable “ class as the target of
the thread.
4. Call the thread’s start( ) method to run the thread.
Below program illustrates the implementation of the above steps:
class X implements Runnable // Step 1
{
public void run ( ) // Step 2
{
for ( int i = 1; i<= 10; i++ )
System.out.println(“ ThreadX “ + i );
System.out.println(“ End of ThreadX “);
}
}
class RunnableTest
{
public static void main ( String args[ ] )
{
X runnable = new X( );
Thread threadX = new Thread( runnable ); // Step 3
threadX.start ( ); // Step 4
System.out.println(“End of main Thread”);
}
}
Inter-Thread Communication
Inter-thread communication is be defined as exchange of message between two or more threads.
The transfer of message takes place before or after the change of state of a thread
For example, an active thread may notify to another suspended thread just before switching to the suspend
state.
Java implements inter-thread communication with the help of following three methods:
notify ( ): resumes the first thread that went into sleep mode. The object declaration of this method is
shown below:
final void notify ( )
notifyall ( ): resumes all the threads that are in sleep mode. The execution of these threads happens as
per priority. The object class declaration of this method is shown below:
final void notifyall ( )
wait ( ): sends calling thread into sleep mode. This thread can now be activated only by above 2
methods. One can also specify the time as parameter for which the thread has to wait. The object class
class declaration of this method is as shown below:
final void wait ( )
All above methods are declared in the root class i.e Object.
Since methods are declared as final they cannot be overridden.
All the three methods throw InterruptedException
sus_res_stop ( String th )
{
th = new Thread ( this.tn );
sus_flag = false;
stop_flag = false;
th.start( );
}
public void run ( )
{
try
{
int j = 1;
while ( ++j < 20 )
{
synchronized ( this );
{
while ( sus_flag )
wait( );
if ( stop_flag )
break;
}
}
}
catch ( InterruptedException IE )
{
System.out.println(“ Thread interrupted “);
}
}
synchronized void my_sus( )
{
sus_flag = true;
}
synchronized void my_resume( )
{
sus_flag = false;
notify( );
}
synchronized void my_stop( )
{
sus_flag = false;
stop_flag = true;
notify ( );
}
}
public class eg_RSR
{
public static void main( String args [ ] )
{
try
{
sus_res_stop SRST = new sus_res_stop( “ SRS“ );
SRST.my_sus( );
System.out.println(“ Thread SRST is suspended “);
Thread.sleep(2000);
SRST.my_resume( );
System.out.println(“ Thread SRST is resumed “);
Thread.sleep(2000);
SRST.my_sus( );
System.out.println(“ Thread SRST is suspended “);
Thread.sleep(2000);
SRST.my_resume( );
System.out.println(“ Thread SRST is resumed “);
Thread.sleep(2000);
SRST.my_stop( );
System.out.println(“ Thread SRST is stopped”);
}
catch ( InterruptedException IE )
{
System.out.println(“ Generated interrupted exception” );
}
}
}
CHAPTER 6
MANAGING ERRORS AND EXCEPTIONS
Introduction
Rarely a program runs successfully at its very first attempt.
A mistake might lead to an error causing to program to produce unexpected results.
Errors are the wrongs that can make program go wrong.
An error may produce an incorrect output or may terminate execution of program abruptly.
It is therefore important to detect and manage it properly.
Types of Errors
Errors may broadly be classified into two categories:
o Compile time error
o Run time error
Compile-time Errors
All syntax errors will be detected and displayed by the Java compiler and therefore these errors are
known as compile-time error.
Whenever the compiler displays an error, it will not create .class file.
Therefore it is necessary to fix all those errors in time.
Java compiler does a nice job of telling us where the errors are in program. For example, missing semi-
colon at the end of the statement.
Example:
System.out.printf(“Hello….”)
For above statement will be “ ‘;’ expected “
o Missing semicolons
o Missing ( or mismatch of ) brackets in classes and methods.
o Misspelling of identifiers and keywords
o Missing double quotes in string
o Use of undeclared variables
o Incompatible types in assignments / initialization
o Bad references to objects
o Use of = in place of = = operator
Run-time Error
Sometimes, program may compile successfully creating .class file but may not run properly.
Such programs may produce wrong results due to wrong logic or may terminate due to errors such as
stack overflow.
Most common run-time errors are:
o Dividing an integer by zero
o Accessing an element that is out of bounds of an array.
o Trying to store value into an array of incompatible class or type
o Trying to cast an instance of class to one of its subclasses
o Passing parameter that is not in valid range for a method
o Attempting to use negative size for an array
o Accessing character that is out of bounds of a string, etc..
Exceptions
An exception is a condition that is caused by run-time error in the program.
When the Java interpreter encounters an error such as dividing an integer by zero, it creates an exception
object and throws.
If the exception object is not caught and handled properly, the interpreter will display an error message as
shown below:
class error
{
public static void main(String args[])
{
int a = 10, b = 5, c = 5;
int x = a / ( b – c );
System.out.println(“ X = “ +x );
int y = a / ( b + c );
System.out.println(“Y = “ +y );
}
}
After compiling above program we get the below error an execution will be terminated:
java . lang . ArithmeticException: / by zero at error.main(error.java:10)
If we want the program to continue with the execution of remaining code, then it should be caught and
display an appropriate message. This task is caked exception handling.
The purpose of exception handling mechanism is to provide a means to detect and report an “exceptional
circumstance” so that appropriate action can be taken.
The mechanism suggests incorporation of separate error handling code that performs the following task:
try Block
Statement that causes
Exception object creator
an exception
Throws
exception
object
catch Block
Statement that handles
Exception handler
an exception
Java uses keyword try to preface block of code that is likely to cause an error condition and “throw” an
exception.
A catch block defined by keyword catch “catches” exception “thrown” by try block and handles it
appropriately.
The catch block is added immediately after try block.
The following example illustrates use of simple try and catch statements:
.............
.............
try
{
statement;
}
catch ( Exception-type e)
{
statement;
}
.............
.............
The try block can have one or more statements that could generate exception.
If any one statement generates an exception, the remaining statements in block are skipped and execution
jumps to catch block.
The catch block too can have one or more statements that are necessary to process the exception.
Every try statement should be followed by at least one catch statement.
The catch statement is passed a single parameter, which is reference to exception object thrown.
If catch parameters matches with type of exception object, then exception is caught and statements in catch
block will be executed.
catch ( Exception-Type-n e )
{
statement;
}
When an exception is n try block is generated, the Java treats the multiple catch statements like cases in
switch statement.
The first statement whose parameter matches with the exception object will be executed, and remaining
statement will be skipped.
A catch statement with an empty block can also be used as follows to avoid program abortion
catch ( Exception e );
The catch statement simply ends with a semicolon, which does nothing.
This statement will catch an exception and then ignore it.
It may be added immediately after try block or after last catch block shown as follows:
try try
{ {
............. .............
............. .............
} }
finally catch(. . . . . )
{ {
............. .............
............. }
} catch (. . . . . )
{
.............
}
finally
{
.............
.............
}
When finally block is defined, code is executed, regardless of whether or not exception is thrown.
We can use it to perform operations like closing files and releasing system resources.
Example:
throw new ArithmeticException( );
throw new NumberFormatException( );
if ( z < 0.01 )
{
throw new MyException ( “ Number is too small “);
}
}
catch ( MyException e)
{
System.out.println(“ Caught my exception “);
System.out.println( e.getMessage( ) );
}
finally
{
System.out.println(“ I am always here “);
}
}
}
The object e which contains the error message “Number is too small” is caught by the catch block which
then displays the message using the getMessage( ) method.
There could be situations where there is a possibility that a method might throw certain kinds of exceptions
but there is no exception handling mechanism prevalent within method.
In such case, it is important that the method caller is intimated explicitly that certain types of exceptions
could be expected from the calledmethod, and the caller must get prepared with some catching mechanism
to deal with it.
The throw clause is used in such situation.
It is specified immediately after the method declaration statement and just before opening brace.