Professional Documents
Culture Documents
Module 1
A Review of structures
Defining a Structure
• To define a structure, you must use the struct statement.
• The struct statement defines a new data type, with more than one
member, for your program.
• The format of the struct statement is this
Syntax: Example:
struct [structure tag] { struct Books {
member definition; char title[50];
member definition; char author[50];
... char subject[100];
member definition; int book_id;
} [one or more structure variables]; } book;
Accessing Structure Members
• To access any member of a structure, we use the member access
operator (.).
• The member access operator is coded as a period between the
structure variable name and the structure member that we wish to
access.
• You would use struct keyword to define variables of structure type.
• Following is the example to explain usage of structure −
#include <iostream> Continued..
#include <cstring> // book 2 specification
strcpy( Book2.title, "Telecom Billing");
using namespace std; strcpy( Book2.author, "Yakit Singha");
strcpy( Book2.subject, "Telecom");
struct Books { Book2.book_id = 6495700;
char title[50];
char author[50]; // Print Book1 info
char subject[100]; cout << "Book 1 title : " << Book1.title <<endl;
int book_id; cout << "Book 1 author : " << Book1.author <<endl;
}; cout << "Book 1 subject : " << Book1.subject <<endl;
cout << "Book 1 id : " << Book1.book_id <<endl;
int main() {
struct Books Book1; // Declare Book1 of type Book // Print Book2 info
struct Books Book2; // Declare Book2 of type Book cout << "Book 2 title : " << Book2.title <<endl;
cout << "Book 2 author : " << Book2.author <<endl;
// book 1 specification cout << "Book 2 subject : " << Book2.subject <<endl;
strcpy( Book1.title, "Learn C++ Programming"); cout << "Book 2 id : " << Book2.book_id <<endl;
strcpy( Book1.author, "Chand Miyan");
strcpy( Book1.subject, "C++ Programming"); return 0;
Book1.book_id = 6495407; }
When the above code is compiled and executed, it
produces the following result −
Book 1 title : Learn C++ Programming
Book 1 author : Chand Miyan
Book 1 subject : C++ Programming
Book 1 id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Yakit Singha
Book 2 subject : Telecom
Book 2 id : 6495700
Procedure–Oriented Programming system
• Procedural Programming can be defined as a programming model
which is derived from structured programming, based upon the
concept of calling procedure.
• Procedures, also known as routines, subroutines or functions, simply
consist of a series of computational steps to be carried out.
• During a program’s execution, any given procedure might be called at
any point, including by other procedures or itself.
• Languages used in Procedural Programming:
• FORTRAN, ALGOL, COBOL,
• BASIC, Pascal and C.
Object oriented programming:
• Object Oriented Programming can be defined as a programming model
which is based upon the concept of objects.
• Objects contain data in the form of attributes and code in the form of
methods.
• In object oriented programming, computer programs are designed using
the concept of objects that interact with real world.
• Object oriented programming languages are various but the most popular
ones are class-based, meaning that objects are instances of classes, which
also determine their types.
• Languages used in Object Oriented Programming:
• Java, C++, C#, Python,
• PHP, JavaScript, Ruby, Perl,
• Objective-C, Dart, Swift, Scala.
Comparison of Object Oriented Language with
Procedure Oriented
PROCEDURAL ORIENTED PROGRAMMING OBJECT ORIENTED PROGRAMMING
In procedural programming, program is In object oriented programming, program is
divided into small parts called functions. divided into small parts called objects.
Procedural programming follows top down Object oriented programming
approach. follows bottom up approach.
There is no access specifier in procedural Object oriented programming have access
programming. specifiers like private, public, protected etc.
Adding new data and function is not easy. Adding new data and function is easy.
Procedural programming does not have any
Object oriented programming provides data
proper way for hiding data so it is less
hiding so it is more secure.
secure.
In procedural programming, overloading is Overloading is possible in object oriented
not possible. programming.
In procedural programming, function is In object oriented programming, data is
more important than data. more important than function.
Procedural programming is based on unreal Object oriented programming is based
world. on real world.
Examples: C, FORTRAN, Pascal, Basic etc. Examples: C++, Java, Python, C# etc.
Console I/O
• C++ I/O occurs in streams, which are sequences of bytes. If bytes flow
from a device like a keyboard, a disk drive, or a network connection
etc. to main memory, this is called input operation
• and if bytes flow from main memory to a device like a display screen,
a printer, a disk drive, or a network connection, etc., this is
called output operation.
The Standard Output Stream (cout)
• The predefined object cout is an instance of ostream class. The cout
object is said to be "connected to" the standard output device, which
usually is the display screen.
• The cout is used in conjunction with the stream insertion operator,
which is written as << which are two less than signs as shown in the
following example.
Example:
#include <iostream> When the above code is compiled and executed,
it produces the following result −
using namespace std;
Value of str is : Hello C++
int main() {
char str[] = "Hello C++";
using namespace std; #When the above code is compiled and executed, it will
prompt you to enter a name. You enter a value and then hit
int main() { enter to see the following result −
char name[50];
Output:
cout << "Please enter your name: "; Please enter your name: cplusplus
cin >> name; Your name is: cplusplus
cout << "Your name is: " << name << endl;
}
Contd..
• The C++ compiler also determines the data type of the entered value
and selects the appropriate stream extraction operator to extract the
value and store it in the given variables.
• The stream extraction operator >> may be used more than once in a
single statement. To request more than one datum you can use the
following −
• cin >> name >> age;
• This will be equivalent to the following two statements −
• cin >> name;
• cin >> age;
Variables in C++
• A variable is a name given to a memory location. It is the basic unit of
storage in a program.
• The value stored in a variable can be changed during program
execution.
• A variable is only a name given to a memory location, all the operations
done on the variable effects that memory location.
• In C++, all the variables must be declared before use.
• A typical variable declaration is of the form:
// Declaring a single variable
type variable_name;
return 0;
}
Output:
x = 20
ref = 30
Function Prototyping
• The Function prototype serves the following purposes –
1) It tells the return type of the data that the function will return.
2) It tells the number of arguments passed to the function.
3) It tells the data types of the each of the passed arguments.
4) Also it tells the order in which the arguments are passed to the
function.
• Therefore essentially, function prototype specifies the input/output
interlace to the function i.e. what to give to the function and what to
expect from the function.
Contd
Ex:
➢ If the assumption and the actual return value are incompatible, then the
compiler will report an error against the function definition and not the function
call.
#include<iostream.h>
int add(int,int); //functionprototype int add(int a,int b)
void main() {
{ return (a+b);
int x,y,z; }
cout<<“Enter a number: ”;
cin>>x;
cout<<“Enter another number:”;
cin>>y;
z=add(x,y); //functioncall
cout<<z<<endl;
}
Contd…
if the function definition is in a different file to be compiled separately, then no
compile-time errors will arise. Instead, wrong results will arise during run time.
/*Beginning of def.c*/
/*function definition*/ /*Beginning of driver.c*/
struct abc void main()
{ {
char a; int x;
int b; x=test(); //no compile time error!!
float c; printf(“%d”,x);
}; }
struct abc test() /*End of driver.c*/
{ Output: 1688
struct abc a1;
a1.a=‘x’;
a1.b=10; The compiler will not be able to convert a
a1.c=1.1; struc abc to an integer.
return a1; Thus, function prototyping guarantees protection
} from errors arising out
/*End of def.c*/ of incorrect function calls.
Function Overloading
➢ C++ allows two or more functions to have the same name, but
different signature.
➢ The compiler decides which function is to be called based upon the number,
type, and sequence of parameters that are passed to the function call.
Example
A function call first matches the prototype having the same number and type of
arguments and then calls the appropriate function for execution.
Contd…
➢ The compiler first tries to find an exact match in which the types of actual
arguments are the same, and use that function.
➢ If an exact match is not found, the compiler uses the integral promotions to the
actual arguments, such as:
char to float
double square(double x)
A function call such as square(10) will cause an error because int can be converted
to either long or double, thereby creating an ambiguous situation as to which
version of square() should be called.
Example
/*Beginning of funcOverload.cpp*/
#include<iostream.h> int add(int a,int b)
int add(int,int); //first prototype {
int add(int,int,int); //second prototype return(a+b);
void main() }
{
int x,y;
x=add(10,20); //matches first prototype
y=add(30,40,50); //matches second prototype int add(int a,int b,int c)
cout<<x<<endl<<y<<endl; {
} return(a+b+c);
}
Output
30
120
Contd…
The two function prototypes at the beginning of the program tell the compiler the
two different ways in which the add() function can be called.
When the compiler encounters the two distinct calls to the add() function, it
already has the prototypes to satisfy them both.Thus, the compilation phase is
completed successfully.
The compiler decides which function is to be called based upon the
number, type, and sequence of parameters that are passed to the
function call.
The first function call, x=add(10,20);
it decides that the function that takes two integers as formal arguments is to be
executed.
Accordingly, the linker then searches for the definition of the add() function
where there are two integers as formal arguments.
Similarly, the second call to the add() function
y=add(30,40,50);
is also handled by the compiler and the linker.
Contd…
Function overloading is also known as function polymorphism because, just like
polymorphism in the real world where an entity exists in more than one form, the
same function name carries different meanings.
struct Distance
{ struct Distance
private: {
int iFeet; void setFeet(int x) //public by default
float fInches; {
public: iFeet=x;
void setFeet(int x) }
{ int getFeet() //public by default
iFeet=x; {
} return iFeet;
int getFeet() }
{ void setInches(float y) //public by default
return iFeet; {
} fInches=y;
void setInches(float y) }
{ float getInches()
//public by default
fInches=y; {
} return fInches;
float getInches() }
{ private:
return fInches; int iFeet;
} float fInches;
}; };
Example
On the other hand, class members are private by default.This is the only difference between the class
keyword and the struct keyword.
class Distance
{
int iFeet; //private by default
float fInches; //private by default
public:
void setFeet(int x)
{
iFeet=x;
}
int getFeet()
{
return iFeet;
}
void setInches(float y)
{
fInches=y;
}
float getInches()
{
return fInches;
}
};
Objects
Variables of classes are known as objects.
An object of a class occupies the same amount of memory as a variable of a
structure that has the same data members.
/*Beginning of objectSize.cpp*/
#include<iostream.h>
struct A
{
char a;
int b;
float c;
};
Its a three-stepprocess
Step 1: Place the class definition in a header file.
/*Beginning of Distance.h*/
/*Header file containing the definition of the Distance class*/
class Distance
{
int iFeet;
float fInches;
public:
void setFeet(int); //prototype only
int getFeet(); //prototype only
void setInches(float); //prototype only
float getInches(); //prototype only
};
/*End of Distance.h*/
Contd…
Step 2: Place the definitions of the member functions in a C++ source file (the library source code).
A file that contains definitions of the member functions of a class is known as the
implementation file of that class. Compile this implementation file and put in a library.
/*Beginning of Distlib.cpp*/
/*Implementation file for the class Distance*/
#include“Distance.h”
void Distance::setFeet(int x) //definition
{
iFeet=x;
}
int Distance::getFeet() //definition
{
return iFeet;
}
void Distance::setInches(float y) //definition
{
fInches=y;
}
float Distance::getInches() //definition
{
return fInches;
}
/*End of Distlib.cpp*/
Contd…
Step 3: Provide the header file and the library, in
whatever media, to other programmers who want to use
this new data type.
Using Classes in Application Programs
Step 1: Include the header file provided by the library programmer in their
source code.
/*Beginning of Distmain.cpp*/
#include“Distance.h”
void main()
{
....
....
}
/*End of Distmain.cpp*/
Step 2: Declare variables of the new data type in their source code.
#include“Distance.h”
void main()
{
Distance d1,d2;
....
....
}
/*End of Distmain.cpp*/
Contd…
/*Beginning of Distmain.cpp*/
/*A sample driver program for creating and using objects of the class
Distance*/
#include<iostream.h>
#include“Distance.h”
void main()
{
Distance d1,d2;
d1.setFeet(2);
d1.setInches(2.2);
d2.setFeet(3);
d2.setInches(3.3);
cout<<d1.getFeet()<<“ ”<<d1.getInches()<<endl;
cout<<d2.getFeet()<<“ ”<<d2.getInches()<<endl;
}
/*End of Distmain.cpp*/
Contd…
Step 4: Compile the source code to get the object file.
Step 5: Link the object file with the library provided by
the library programmer to get the executable or
another library.
this Pointer
The facility to create and call member functions of class objects is provided by
the C++ compiler.
The compiler does this by using a unique pointer known as the this pointer.
The this pointer is always a constant pointer.The this pointer always points
at the object with respect to which the function was called.
After the compiler has ascertained that no attempt has been made to access the
private members of an object by non-member functions, it converts the C++
code into an ordinary C language code as follows:
1. It converts the class into a structure with only data members as follows.
Before After
class Distance
{
int iFeet; struct Distance
float fInches; {
public: int iFeet;
void setFeet(int); //prototype only float fInches;
int getFeet(); //prototype only };
void setInches(float); //prototype only
float getInches(); //prototype only
};
Contd…
2. It puts a declaration of the this pointer as a leading formal argument in the
prototypes of all member functions as follows.
Before
void setFeet(int);
After
void setFeet(Distance * const,int);
Before
int getFeet();
After
int getFeet(Distance * const);
Before
void setInches(float);
After
void setInches(Distance * const,float);
Before
float getInches();
After
float getInches(Distance * const);
Contd…
3. It puts the definition of the this pointer as a leading formal argument in the
definitions of all member functions as follows.
It also modifies all the statements to access object members by accessing them
through the this pointer using the pointer-to-member access operator (->).
Before After
void Distance::setFeet(int x) void setFeet(Distance * const this, int x)
{ {
iFeet=x; this->iFeet=x;
} }
Before After
int Distance::getFeet() int getFeet(Distance * const this)
{ {
return iFeet; return this->iFeet;
} }
Contd…
Before After
float Distance::getInches() float getInches(Distance * const this)
{ {
return fInches; return this->fInches;
} }
The scope resolution operator is also an operator. Just like any other operator,
it operates upon its operands.
The scope resolution operator is abinary operator,thatis,ittakes two operands.
Based upon this information, the scope resolution operator inserts a constant
operator of the correct type as a leading formal argument to the function on its
right.
For example, if the class name is Distance, as in the above case, the compiler
inserts a pointer of type Distance * const as a leading formal argument to the
function on its right.
Contd…
4. It passes the address of invoking object as a leading parameter to each call to
the member functions as follows.
Before After
d1.setFeet(1); setFeet(&d1,1);
Before After
d1.setInches(1.1); setInches(&d1,1.1);
Before After
cout<<d1.getFeet()<<endl; cout<<getFeet(&d1)<<endl;
Before After
cout<<d1.getInches()<<endl; cout<<getInches(&d1)<<endl;
Contd…
It is evident that the this pointer should continue to point at the same object—
the object with respect to which the member function has been called—
throughout its lifetime. For this reason, the compiler creates it as aconstant
pointer.
/*Beginning of Distlib.cpp*/
#include“Distance.h”
/*Beginning of Distance.h*/ Distance Distance::add(Distance dd)
class Distance {
{ Distance temp;
/* temp.iFeet=iFeet+dd.iFeet; //legalto access both
rest of the class Distance //temp.iFeet and dd.iFeet
temp.fInches=fInches+dd.fInches; //ditto
*/ return temp;
Distance add(Distance); }
}; /*
/*End of Distance.h*/ definitions of the rest of the functions of class
Distance
*/
/*End of Distlib.cpp*/
Contd…
Ooooooooooooooooooooooooooooooooooo
o
/*Beginning of Distmain.cpp*/
#include<iostream.h>
#include“Distance.h”
void main()
{
Distance d1,d2,d3;
d1.setFeet(1);
d1.setInches(1.1);
d2.setFeet(2);
d2.setInches(2.2);
d3=d1.add(d2);
cout<<d3.getFeet()<<“’-”<<d3.getInches()<<“’’\n”;
}
/*End of Distmain.cpp*/
Outpu
t 3-
3.3
Contd...
The definition of Distance :: add() function, after the previously described conversion by
the compiler is carried out, will appear as follows.
Distance add(Distance * const this, Distance dd)
{
Distance temp;
temp.iFeet=this->iFeet+dd.iFeet;
temp.fInches=this->fInches+dd.fInches;
return temp;
}
When this function is called from the main() function with respect to ‘d1’, the this
pointer points at ‘d1’. Thus, it is the private data member of ‘d1’ that is being accessed
in the second and third lines of the add() function.
So, now we can
▪ Declare a class
▪ Define member data and member functions
▪ Make members private and public
▪ Declare objects and call member functions with respect to objects
Contd…
Once again, the importance of compile-time errors over run-time errors is
emphasized.
A pure C compiler would not recognize this statement as an invalidaccess.
Thus, creating bug-free executables is difficult and unreliable in C. This is due to the
absence of language constructs that enforce data security.
On the other hand, a C++ compiler that also detects invalid access of private
data members would immediately throw an error during compile time itself and
prevent the creation of the executable.Thus, creating bug-free executables is easier
and more reliable in C++ than in C.This is due to the presence of language constructs
that enforce data security.
Data Abstraction
Data abstraction is a virtue by which an object hides its internal operations from the rest
of the program.
It makes it unnecessary for the client programs to know how the data is internally
arranged in the object.
Now, in order to understand this concept, let us take an example in C++.The library
programmer, who has designed the Distance class, wants to ensure that the fInches portion
of an object of the class should never exceed 12
Example
If a value larger than 12 is specified by an application programmer while calling
the Distance::setInches() function, the logic incorporated within the definition of
the function should automatically increment the value of iFeet and
decrement the value of fInches by suitable amounts.
void Distance::setInches(float y)
{
fInches=y;
if(fInches>=12)
{
iFeet+=fInches/12;
fInches-=((int)fInches/12)*12;
}
}
Here, we notice that an application programmer need not send values less than 12 while
calling the Distance::setInches() function. The default logic within the
Distance::setInches() function does the necessary adjustments. This is an example of data
abstraction.
Contd…
Similarly, the definition of the Distance::add() function should also be modified as
follows by the library programmer. Here, it can be assumed that the value of
fInches portion of neither the invoking object nor the object appearing as formal
argument (‘dd’) can be greater than 12.
then the value of d3.fInches will become 3 (not 15) and the value of d3.iFeet will become
4 (not 3).
Contd…
It has already been mentioned that real-world objects never attain an invalid
state.They also do not start in an invalid state.
Let us continue with our earlier example—the Distance class. Recollect that it is
the library programmer’s intention to ensure that the value of fInches portion
of none of the objects of the class Distance should exceed 12.
/*Beginning of DistJunk.cpp*/
#include<iostream.h>
#include“Distance.h”
void main()
{
Distance d1;
cout<<d1.getFeet()<<“ ”<<d1.getInches()<<endl;
}
/*End of DistJunk.cpp*/ Output
297 34.56
Contd…
As you can see, the value of fInches of ‘d1’is larger than 12! This happened
because the value of both iFeet and fInches automatically got set to junk values
when ‘d1’ was allocated memory and the junk value is larger than 12 for
d1.fInches.
Thus, the objective of the library programmer to keep the value of fInches less
than 12 has not yet been achieved.
It would be unrealistic to expect that an application programmer will explicitly
initialize each object that is declared.
Distance d1;
d1.setFeet(0); //initialization
d1.setInches(0.0); //initialization
Data abstractionis effectivedue todata hidingonly.
On the other side of the coin, in C language, life becomes difficult for an
application programmer also. If a certain member of a structure variable acquires
an invalid or a wrong value, he/she has to hunt through the entire source code
to detect the bug.
Perfect definitions of the member functions are guaranteed to achieve their objective
because ofdata hiding.
Explicit Address Manipulation
An application programmer can manipulate the member data of any object by
explicit address manipulation.
/*Beginning of DistAddrManip.cpp*/
#include“Distance.h”
#include<iostream.h>
void main()
{
Distance d1;
d1.setFeet(256);
d1.setInches(2.2);
char * p=(char *)&d1; //explicit address manipulation
*p=1; //undesirable but unpreventable
cout<<d1.getFeet()<<“ ”<<d1.getInches()<<endl;
}
/*End of DistAddrManip.cpp*/
However, such explicit address manipulation by an application programmer cannot
be prevented.
Arrow Operator
Member functions can be called with respect to an object through a pointer
pointing at the object.
The arrow operator (->) does this.
/*Beginning of PointerToMember.cpp*/
#include<iostream.h>
#include“Distance.h”
void main()
{
Distance d1; //object
Distance * dPtr; //pointer
dPtr=&d1; //pointer initialized
/*Same as d1.setFeet(1) and d1.setInches(1.1)*/
dPtr->setFeet(1); //calling member functions
dPtr->setInches(1.1); //through pointers
/*Same as d1.getFeet() and d1.getInches()*/
cout<<dPtr->getFeet()<<“ ”<<dPtr->getInches()<<endl;
}
/*End of PointerToMember.cpp*/
Contd…
It is interesting to note that just like the dot (.) operator, the definition of the arrow
(->) operator has also been extended in C++.
It takes not only data members on its right as in C, but also member
functions as its right-hand side operand.
If the operand on its right is a data member, then the arrow operator behaves
just as it does in C language.
However, if it is a member function of a class where a pointer of the same class
type is its left-hand side operand, then the compiler simply passes the value of
the pointer as an implicit leading parameter to the function call.
dPtr->setFeet(1); setFeet(dPtr,1);
Now, the value of dPtr is copied into the this pointer.Therefore, the this pointer
also points at the same object at which dPtr points.
Calling One Member Function from Another
/*Beginning of NestedCall.cpp*/
class A
{
int x;
public: void main()
void setx(int); {
A A1;
void setxindirect(int);
A1.setxindirect(1);
}; }
void A::setx(int p) /*End of NestedCall.cpp*/
{
x=p;
}
void A::setxindirect(int q)
{
setx(q);
}
Contd…
The call to the A::setxindirect() function changes from
A1.setxindirect(1);
to
setxindirect(&A1,1);
The definition of the A::setxindirect() function changes from
void A:: setxindirect(int q)
{
setx(q);
}
to
void setxindirect(A * const this, int q)
{
this->setx(q); //calling function through a pointer
}
Contd…
void A::show()
#include<iostream.h> {
class A cout<<“Hello\n”;
{ }
public: void A::show(int x)
void show(); {
void show(int); for(int i=0;i<x;i++)
}; cout<<“Hello\n”;
}
void main()
{
A A1;
A1.show(); //first definitioncalled
A1.show(3); //second definition called
}
Contd…
Consider the following example
classA
{
public:
void show();
};
class B
{
public:
void show();
};
A function of the same name show() is defined in both the classes—‘A’ and ‘B’.The
signature also appears to be the same.
But with our knowledge of the this pointer, we know that the signatures are actually different.
class A;
class B
{
A *APtr;
public:
void Map(const A * const);
void test_friend(const int=0);
};
class A
{
int x;
public:
friend void B::test_friend(const int=0);
};
/*End of friendMemFunc.h*/
Contd…
Another problem arises if we try to define the B::test_friend() function as an
inline function by defining it within class B itself.
class B
{
/*
rest of the class B
*/
friend void ab(const A&,const B&);
};
Static Members
Static member data: Static data members hold global data that is common to all
objects of the class. Examples of such global data are
1) count of objects currently present,
2) common data accessed by all objects, etc.
Let us consider class Account. We want all objects of this class to calculate
interest at the rate of say 4.5%. Therefore, this data should be globally available to
all objects of this class.
This data cannot and should not be a member of the objects themselves.
Otherwise, multiple copies of this data will be embedded within the objects taking
up unnecessary space.
Same value would have to be maintained for this data in all objects.This is very
difficult.Thus, this data cannot be stored in amember variable of classAccount.
At the same time, this data should not be stored in a global variable. Then the data
is liable to be changed by even non-member functions. It will also potentially lead
to name conflicts.
O H H H H H H H H … … … … … … … … Now howthis conflict can be resolved??
Contd…
Storing the data in a static variable of the class resolves this conflict.
Static data members are members of the class and not of any object of the class, that is, they are
not contained inside any object.
We prefix the declaration of a variable within the class definition with the keyword static to
make it a static data member of the class.
/*Beginning of Account.h*/
class Account
{
static float interest_rate; //a static data member
/*
rest of the class Account
*/
};
/*End of Account.h*/
A statement declaring a static data member inside a class will obviously not cause any memory
to get allocated for it.
Moreover, memory for a static data member will not get allocated when objects of the class are
declared.
This is because a static data member is not a member of any object.Therefore, we must not
forget to write the statement to define (allocate memory for) a static member variable.
Contd…
Explicitly defining a static data member outside the class is necessary. Otherwise,
the linker produces an error.
The following statement allocates memory for interest_rate member of class
Account.
floatAccount::interest_rate;
The above statement initializes interest_rate to zero. If some other initial value
(say 4.5) is desired instead, the statement should be rewritten as follows.
floatAccount::interest_rate=4.5;
Static data members should be defined in the implementation files only. The
header file is included in both the implementation file and the driver program.
Making static data members private prevents any change from non-member
functions as only member functions can change the values of static data
members.
Introducing static data members does not increase the size of objects of the
class. Static data members are not contained within objects.There is only one
copy of the static data member in the memory.
Example
Static data members can be of any type.
/*Beginning of Account.h*/
/*Beginning of staticSize.cpp*/ class Account
#include<iostream.h> class A {
{ static float interest_rate;
int x; char y; static char name[30];
float z; /*
static float s; rest of the class Account
*/
};
};
float A::s=1.1; void /*End of Account.h*/
main()
{
cout<<sizeof(A)<<endl; /*Beginning of Account.cpp*/
} #include“Account.h”
/*End of staticSize.cpp*/ float A::interest_rate=4.5;
char A::name[30]=“The Rich and Poor Bank”;
/*
definitions of the rest of the functions of class Account
*/
/*End of Account.cpp*/
Example
/*Beginning ofAccount.h*/
class Account
{
static int nameLength=30;
static char name[nameLength];
/*
rest of the class Account
*/
};
/*End ofAccount.h*/
/*Beginning ofAccount.cpp*/
#include“Account.h”
int A::nameLength;
char A::name[nameLength]=“The Rich and Poor Bank”;
/*
definitions of the rest of the functions of class Account
*/
/*End ofAccount.cpp*/
the variable nameLength is referred to directly without the class name and the scope resolution operator
while defining the variable name. One static data member can directly refer to another without using the
scope resolution operator.
Contd…
We must notice that the static data member that has been initialized inside the
class must be still defined outside the class to allocate memory for it.
Non-integral static data members cannot be initialized like this.
/*Beginning of Account.h*/
class Account
{
static char name[30]=“The Rich and Poor Bank”; //error!!
/*
rest of the classAccount
*/
};
/*End ofAccount.h*/
Contd…
Member functions can refer to static data members directly.
/*Beginning ofAccount.h*/
#include“Account.h”
classAccount
float Account::interest_rate=4.5;
{ void Account::updateBalance()
static float interest_rate; {
public: if(end_of_year)
void updateBalance();
/* balance+=balance*interest_rate/100;
rest of the class Account }
*/ /*
definitions of the rest of the functions of
};
classAccount
/*End ofAccount.h*/ */
/*Beginning ofAccount.cpp*/ /*End of Account.cpp*/
Contd…
The object-to-member access operator can be used to refer to the static data
member of a class with respect to an object.
The class name with the scope resolution operator can do this directly.
f=a1.interest_rate; //a1is an object of the class Account
f=Account::interest_rate;
There are some things static data members can do but non-static data members
cannot.
1)A static data member can be of the same type as the class of which it is a member.
class A
{
static A A1; //OK :static
A * APtr; //OK :pointer
A A2; //ERROR!! :non-static
};
A static data member can appear as the default value for the formal arguments of member
functions of its class.
Contd…
classA
{
static int x;
int y;
public:
void abc(int=x); //OK
void def(int=y); //ERROR!! :object required
};
A static data member can be declared to be a constant. In that case, the member functions
will be able to only read it but not modify its value.
Static member functions :
How do we create a member function that need not be called with respect to an existing object?
This function’s sole purpose is to access and/or modify static data members of the class.
Static member functions fulfill the above criteria.
Prefixing the function prototype with the keyword static specifies it as a static member
function. However, the keyword static should not reappear in the definition of the function.
Contd…
Suppose there is a function set_interest_rate() that sets the value of the
interest_rate static data member of class Account.
The application programmer should be able to call this function even if no objects
have been declared. As discussed previously, this function should be static.
/*Beginning of Account.h*/
classAccount
{
static float interest_rate;
public:
static void set_interest_rate(float);
/*
rest of the class Account
*/
};
/*End of Account.h*/
/*Beginning of Account.cpp*/
#include“Account.h”
float Account::interest_rate = 4.5;
void Account::set_interest_rate(float p)
{
interest_rate=p;
}
/*
definitions of the rest of the functions of class Account
*/
/*End of Account.cpp*/
Objects and Functions
Objects can appear as local variables inside functions.They can also be passed by value or
by reference to functions.
/*Beginning of Distance.h*/
class Distance /*End of Distance.cpp*/
/*Beginning of Distance.cpp*/
{ /*Beginning of Distmain.cpp*/
#include“Distance.h”
public: #include<iostream.h>
Distance Distance::add(Distance dd)
/*function to add the #include“Distance.h”
{
invoking object with void main()
Distance temp;
another {
temp.iFeet=iFeet+dd.iFeet;
object passed as a Distance d1,d2,d3;
temp.setInches(fInches+dd.fInches);
parameter and return the d1.setFeet(5);
return temp;
resultant d1.setInches(7.5);
}
object*/ d2.setFeet(3);
/*
d2.setInches(6.25);
definitions of the rest of the
Distance add(Distance); d3=d1.add(d2);
functions of class
/* cout<<d3.getFeet()<<“
Distance
rest of the class Distance ”<<d3.getInches()<<endl;
*/
*/ }
/*End of Distance.cpp*/
}; /*End of Distmain.cpp*/
/*End of Distance.h*/
Contd…
They can be returned by the value or by functions.
Arrays of Objects :
It is possible to create array of objects.
➢ We can have arrays of variables that are of the type class.
Such variables are called arrays of objects.
Name
Manager[0]
Age
Name
Manager[1]
Age
Name
Manager[2]
Age
Example
#include“Distance.h”
#include<iostream.h>
#define SIZE 3
void main()
{
Distance dArray[SIZE];
int a;
float b;
for(int i=0;i<SIZE;i++)
{
cout<<“Enter the feet :”;
cin>>a;
dArray[i].setFeet(a);
cout<<“Enter the inches :”;
cin>>b;
dArray[i].setInches(b);
}
for(int i=0;i<SIZE;i++)
{
cout <<dArray[i].getFeet()<<“ ” <<dArray[i].getInches()<<endl;
}
}
/*End of DistArray.cpp*/
Arrays inside Objects
➢An array can be declared inside aclass.
➢Such an array becomes a member of all objects of the class.
➢It can be manipulated/accessed by all member functions of the class.
Ex: class example #define SIZE 3
/*A class to duplicate the behaviour of an integer array*/
{ class A
{
int arr[10]; int iArray[SIZE];
public:
------- void setElement(unsigned int,int);
int getElement(unsigned int);
------- };
/*function to write the value passed as second parameter at the position passed
} as first parameter*/
void A::setElement(unsigned int p,int v)
{
if(p>=SIZE)
return; //better to throw an exception
iArray[p]=v;
}
/*function to read the value from the position passed as parameter*/
int A::getElement(unsigned int p)
{
if(p>=SIZE)
return –1; //better to throw an exception
return
Namespaces
Namespaces enable the C++ programmer to prevent pollution of the global
namespace that leads to nameclashes.
The term ‘global namespace’ refers to the entire source code. It also includes all
the directly and indirectly included header files.
By default, the name of each class is visible in the entire source code, that is, in
the global namespace.
It leads to following problems
/*Beginning ofA1.h*/
class A
{
}; Now, let us include both these
/*End ofA1.h*/ header files in a program and
/*Beginning ofA2.h*/ see what happens if we declare
class A //a class with an existing name an object of the class.
{
};
/*End ofA2.h*/
Contd….
/*Beginning of multiDef01.cpp*/
#include”A1.h” The global visibility of
#include”A2.h” the definition of class A makes the
void main() inclusion of the two header files
{ mutually exclusive.
A AObj; //ERROR: Ambiguity error dueto
//multiple definitions of A Consequently, this also makes use of
} the two definitions of class A
/*End of multiDef01.cpp*/ mutually exclusive.
/*Beginning ofA1.h*/
namespace A1 //beginning of a namespace A1 /*Beginning of using.cpp*/
{ #include“A1.h”
class A #include“A2.h”
{ void main()
}; {
} //endof a namespaceA1 using namespace A1;
/*End of A1.h*/ A AObj1; //OK: AObj1 is anobject
/*Beginning ofA2.h*/ of the class defined in
namespace A2 //beginning of a namespace A2 A1.h
{
class A A2::AAObj2; //OK: AObj2 is an
{ object of the class
}; defined in A2.h
} //end of a namespace A2 }
/*End of A2.h*/ /*Beginning of using.cpp*/
Now, the two definitions of the class are enveloped in two different namespaces. The
corresponding namespace, followed by the scope resolution operator, must be prefixed to
the name of the class while referring to it anywhere in the source code. Thus, the
ambiguity encountered in the above listing can be overcome.
Contd…
However, we must note that the using directive brings back the global namespace
pollution that the namespaces mechanism was supposed to remove in the first
place!
The last line in the above listing compiles only because the class name was
qualified by the name of the namespace.
Some namespaces have long names. Qualifying the name of a class that is enclosed
within such anamespace, with the name of the namespace, is cumbersome.
/*Beginning of longName01.cpp*/
namespace a_very_very_long_name
{
class A
{
};
}
void main()
{
a_very_very_long_name::AA1; //cumbersome long name
}
/*End of longName01.cpp*/
Contd…
Assigning a suitably short alias to such a long namespace name solves the problem as
illustrated
/*Beginning of longName02.cpp*/
namespace a_very_very_long_name
{
class A
{
};
}
namespace x = a_very_very_long_name; //declaring an alias
void main()
{
x::A A1; //convenient short name
}
/*End of longName02.cpp*/
Aliases provide an incidental benefit also. Suppose an alias has been used at a number
of places in the source code.
Changing the alias declaration so that it stands as an alias for a different namespace
will make each reference of the enclosed class refer to a completely different class.
Contd…
Suppose an alias X refers to a namespace‘N1’.
namespace X = N1; //declaring an alias
Further, suppose that this alias has been used extensively in the source code.
X::AAObj; //AObj is an object of class A that is enclosed in
namespace N1.
AObj.f1(); //f1() is a member function of the aboveclass.
/*Beginning of nestPublic.h*/
/*Beginning of nestPrivate.h*/
class A
class A
{
{
public:
class B
class B
{
{
/*
/*
definition of class B
definition of class B
*/
*/
};
};
/*
/*
definition of class A
definition of class A
*/
*/
};
};
/*End of nestPrivate.h*/
/*End of nestPublic.h*/
Contd…
A nested class is created if it does not have any relevance outside its enclosing
class. By defining the class as a nested class, we avoid a namecollision.
In Above Listings ,even if there is a class B defined as a global class, its name will not
clash with the nested class B.
/*Beginning of nestSize.cpp*/
#include<iostream.h>
class A
{
int x;
public:
class B
{
int y;
};
};
void main()
{ Output
cout<<sizeof(int)<<endl; 4
cout<<sizeof(A)<<endl;
4
}
/*End of nestSize.cpp*/
Contd…
Member functions of a nested class can be defined outside the definition of the
enclosing class.
This is done by prefixing the function name with the name of the enclosing class
followed by the scope resolution operator.
This, in turn, is followed by the name of the nested class followed again by the
scope resolution operator.
/*Beginning of nestClassDef.h*/
class A
{
/*Beginning of nestClassDef.cpp*/
public: #include“nestClassDef.h”
class B void A::B::BTest()
{ {
public: //definition of A::B::BTest()function
void BTest(); //prototype only }
}; /*
/*
definition of class A
definitions of the rest of the functions of class B
*/ */
}; /*End of nestClassDef.cpp*/
/*End of nestClassDef.h*/
Contd…
A nested class may be only prototyped within its enclosing class and defined later.
Again, the name of the enclosing class followed by the scope resolution operator
is required.
/*Beginning of nestClassDef.h*/
class A
{
class B; //prototype only
};
class A::B
{
/*
definition of the class B
*/
};
/*End of nestClassDef.h*/
Objects of the nested class are defined outside the member functions of the
enclosing class in much the same way (by using the name of the enclosing class
followed by the scope resolution operator).
A: :BB1;
However, the above line will compile only if class B is defined within the public
section of class A. Otherwise, a compile-time error willresult.
Contd…
An object of the nested class can be used in any of the member functions of the
enclosing class without the scope resolution operator.
Moreover, an object of the nested class can be a member of the enclosing class.
In either case, only the public members of the object can be accessed unless the
enclosing class is a friend of the nested class.
/*Beginning of nestClassObj.h*/
classA /*Beginning of nestClassObj.cpp*/
{ #include“nestClassObj.h”
class B void A::ATest()
{ {
public: B1.BTest();
void BTest(); //prototype only
B B2;
};
B B1; B2.BTest();
public: }
voidATest(); /*End of nestClassObj.cpp*/
};
/*End of nestClassObj.h*/
Contd…
Member functions of the nested class can access the non-static public members
of the enclosing class through an object, a pointer, or a reference only.
/*Beginning of enclClassObj.h*/
classA
#include“enclClassObj.h”
{
public: void A::B::BTest(A&ARef)
void ATest(); {
class B ARef.ATest(); //O K
{ }
public: voidA::B::BTest1()
void BTest(A&); {
void BTest1( ); ATest(); //ERRO R!!
}; }
}; /*End of enclClassObj.cpp*/
/*End of enclClassObj.h*/
}
/*Beginning ofA.h*/
/*Beginning ofAMain.cpp*/
classA
#include“A.h”
{
void main()
int x;
{
public:
A A1; //object declared … constructor
void setx(const int=0);
called
int getx();
}
};
/*End ofAMain.cpp*/
/*End ofA.h*/
Contd…
The statement in the function main() is transformed into the following
statements.
A A1; //memory allocated for the object (4 bytes)
A1.A( ); //constructor called implicitly by compiler
The second statement above is then transformed to
A(&A1);
Similarly, the constructor is called for each object that is created dynamically in
the heap by the new operator.
A *APtr;
APtr = new A; //constructor called implicitly by
compiler
The second statement above is transformed into the following two statements.
APtr = new A; //memory allocated
APtr->A( ); //constructor called implicitly by compiler
The second statement above is then transformed into
A(APtr);
Contd…
The foregoing explanations make one thing very clear.
Unlike their name, constructors do not actually allocate memory for objects.
They are member functions that are called for each object immediately after
memory has been allocated for the object.
Contd…
A constructor guarantees that an object created by the class will be initialized automatically.
Contd…
Ex: create an object
integer int1;
➢ Object int1 is created, and also initializes its data members m and n to zero.
Default Constructor
➢ Accepts no parameters.
➢ We can pass the arguments to constructor function when object are created.
Contd…
➢ We must pass the initial values as arguments to the constructor function when an object is
declared.
➢ This statement creates an integer object int1 and passes the values 10 and 100 to it.
➢ Also called as short hand method, shorter, better and easy to implement.
Contd…
Contd…
Copy Constructor
➢ Copy Constructor is used to declare and initialize an object from another object.
➢ Ex:
integer I2 ( I1 );
➢ This would define an object I2 and at the same time initialize it to the values of I1.
➢ Another form:
➢ The default argument constructor can be called with either one argument or no
arguments.
/*Beginning of A.cpp*/
#include”A.h”
class A
#include<iostream.h>
{ A::A() //our own constructor
int x; {
public: cout<<”Constructor of class A called\n”;
A(); //our own constructor }
void setx(const int=0); /*
int getx(); definitions of the rest of the functions of class A
}; */
/*End of A.h*/ /*End of A.cpp*/
/*Beginning of AMain.cpp*/
#include<iostream.h>
#include“A.h”
void main()
{
A A1;
cout<<”End of program\n”;
}
/*End of AMain
Destructors
➢ Used to destroy the objects that have been created by a constructor.
➢ The destructor is a member function whose name is the same as the class name
but is preceded by a tilde( ~).
~integer( ) { }
➢ Destructor never takes any argument nor does it return any value.
➢ It will be invoked implicitly by the compiler upon exit from the program to
clean up storage that is no longer accessible. (No need to call it explicitly)
➢ Constructors.cpp
➢ Destructors.cpp
➢ DestructoroutofScope.cpp
➢ beforeDestructor.cpp
➢ CopyConstructors.cpp
➢ OverloadedConstructors.cpp
➢ ParameterizedConstructors.cpp
Contd…
Ex: void main( )
{
AA1;
} //A1 goes out of scope here
‘A1’ goes out of scope just before the main() function terminates. At this point, the
compiler embeds a call to the destructor for ‘A1’. It embeds the following statement.
A1.~A(); //destructorcalled
• The destructor will also be called for an object that has been dynamically created in the
heap just before the delete operator is applied on the pointer pointing at it.
A * APtr;
APtr = new A; //object created … constructor called ........
deleteAPtr; //object destroyed … destructor called
The last statement is transformed into
APtr->~A( ); //destructor called for *APtr
deleteAPtr; //memory for *APtr released
Contd…
The destructor does not ‘destroy’ or deallocate memory that an object occupies.
It is merely a member function that is called for each object just before the object
goes out of scope (gets destroyed).
Before
After
classA classA
{ {
....
........ Public:
public: ~A(); //prototype inserted implicitly by compiler
....... ....
};
}; A::~A( )
void main( ) {
//empty definition inserted implicitly by compiler
{
}
A A1; void main( )
} {
A A1;
A1.~A( );
}
Contd…
/*Beginning ofA.h*/
classA
{
int x;
public:
A( ); /*Beginning ofAMain.cpp*/
void setx(const int=0); #include“A.h”
int getx(); #include<iostream.h>
~A( ); //our own destructor
};
void main()
/*End ofA.h*/ {
/*Beginning of A.cpp*/ A A1;
#include“A.h” cout<<“End of program\n”;
#include<iostream.h>
A::A() }
{ /*End ofAMain.cpp*/
cout<<“Constructor of class A called\n”;
}
A::~A() //our own destructor
{
cout<<“Destructor of class A called\n”;
}
/*
definitions of the rest of the functions of class A
*/
/*End ofA.cpp*/
Zero-argument Constructor Example
Output
Constructor of Class A called
End of rogram
Parameterized Constructor
O utput 1 1.1
Introduction to Java
Java Programming Basics
• Java is one of the most popular and widely used programming
language and platform.
• A platform is an environment that helps to develop and run programs
written in any programming language.
• Java is fast, reliable and secure.
• Applications: From desktop to web applications, scientific
supercomputers to gaming consoles, cell phones to the Internet, Java is
used in every nook and corner.
• Java was originally developed by James Gosling at Sun Microsystems
(which has since been acquired by Oracle) and released in 1995 as a
core component of Sun Microsystems' Java platform.
• The original name of this language was Oak.
• Later the project went by the name Green and was finally
renamed Java.
Java’s Magic: The Byte code
• What is Bytecode
• Java program is compiled bytecode is generated.
• To be more precise a Java bytecode is the intermediate code in the
form of a .class file.
• Bytecode in Java is the reason java is platform-independent.
Step by step Execution of Java Program:
• Whenever, a program is written in JAVA, the javac compiles it.
• The result of the JAVA compiler is the .class file or the bytecode and
not the machine native code (unlike C compiler).
• The bytecode generated is a non-executable code and needs an
interpreter to execute on a machine. This interpreter is the JVM and
thus the Bytecode is executed by the JVM.
• And finally program runs to give the desired output.
Java Development Kit
• Three core technology packages
• The JVM(Java Virtual Machine):
• is the Java platform component that executes programs.
• The JRE(Java Runtime Environment):
• is the on-disk part of Java that creates the JVM.
• The JDK(Java Development Kit):
• allows developers to create Java programs that can be executed
and run by the JVM and JRE.
The JDK(Java Development Kit):
• JDK is a collection of tools that are used to create Java programs that
can be executed and run by the JVM and JRE.
• It consists of
• javac-the java compiler that translates the source code to the bytecode
form and stores it in a separate class file.
• java-java interpreter, which interprets the bytecode stored in the class
file and executes the program to generate output.
• javadoc- for creating html document for documentation from source
code file.
• javah-it produces header files for the use of native methods
• jdb- java debugger which helps to find errors in the program
• appletviewer- for executing java applet.
Following are the steps that illustrates
execution process of the application program
• The user creates java source code in the text editor.
• The source is compiled using the javac command.
• javadoc tool can be used to create the HTML files that document the
source program.
• On compiling the source code a class file will get generated which
consists of the bytecode.
• The developer may use javah tool for generating the required header
files.
• The class file produced by javac can be interpreted using java in
order to execute the program.
Java Buzzwords
• Features:
• Simple
• Object Oriented
• Robust:
• Strictly typed language
• Memory management through garbage collection
• Exception handling
• Multithreaded:
• Interactive, networked programs
• Architectural Neutral:
• “Write once, run anywhere, anytime, forever”
• Interpreted and high performance
• Distributed :
• Designed for distributed environment of the internet because it handles TCP/IP
protocol suite.
• Dynamic:
• Dynamically linking new libraries, methods and objects
Object Oriented Programming
There are four main OOP concepts in Java.
These are:
• Abstraction
• Encapsulation
• Inheritance
• Polymorphism
Abstraction
• Abstraction means using simple things to represent complexity.
• Data Abstraction is the property by virtue of which only the essential
details are displayed to the user.
• Abstraction means simple things like objects, classes,
and variables represent more complex underlying code and data.
Encapsulation:
• Binding together the code and the data it manipulates and keeps them safe
from outside interface and misuse.
• Classes, objects, access specifiers
Class & Object
• A class is a user defined blueprint or prototype
• It represents the set of properties or methods that are common to all objects
of one type
• Syntax:
class classname
{
Data members
Member functions
};
• Objects are instances/occurrences of a class.
Inheritance
• It is the mechanism in java by which one class is allowed to inherit the
features(fields and methods) of another class.
• Important terminology:
• Super Class: The class whose features are inherited is known as super class(or a
base class or a parent class).
• Sub Class: The class that inherits the other class is known as sub class(or a
derived class, extended class, or child class). The subclass can add its own fields
and methods in addition to the superclass fields and methods.
• Reusability: Inheritance supports the concept of “reusability”, i.e. when we want
to create a new class and there is already a class that includes some of the code
that we want, we can derive our new class from the existing class. By doing this,
we are reusing the fields and methods of the existing class.
Polymorphism
• The word “poly” means many and “morphs” means forms, So it means
many forms.
• Polymorphism is considered as one of the important features of Object
Oriented Programming.
• Polymorphism allows us to perform a single action in different ways.
• Method Overloading
• Operator Overloading
First Sample Program
• A source file officially is a compilation unit.
• It is a text file that contains one or more class definitions.
• This file use the .java filename extension.
• In java all code must reside inside a class.
• The name of that class should match the name of the file that hold
the program.
• Also the capitalization of filename should match the classname.
Sample Program
• Example:
• Filename: Example.java
/* This is a simple java program.
Call this file “Example.java”. */
class Example
{
// your program begins with a call to main()
public static void main(String args[])
{
system.out.println(“ This is a sample java program”);
}
}
Compiling the program
• Compile the program:
• Command: javac Example.java
• The javac compiler creates a file called Example.class that is the bytecode
version of the program.
• It contains intermediate representation of the program that contains
instructions the JVM will execute.
• Run the program:
• Command: java Example
• When the program is run the following output will be displayed:
This is a simple java program.
Control Statements in Java
• In programming we face some situations where we want a certain
block of code to be executed when some condition is fulfilled.
• A programming language uses control statements to control the flow
of execution of program based on certain conditions.
• In Java, the control statements are divided into three categories which
are selection statements, iteration statements, and jump statements.
Java’s Selection statements:
• if
• if-else
• nested-if
• if-else-if
• switch-case
If statement:
• is the most simple decision making statement.
• It is used to decide whether a certain statement or block of
statements will be executed or not i.e if a certain condition is true
then a block of statement is executed otherwise not.
• Syntax: Flowchart:
if(condition)
{
// Statements to execute if
// condition is true
}
class IfDemo
{
public static void main(String args[])
{
int i = 10;
if (i > 15)
System.out.println("10 is less than 15");
I am Not in if
if-else:
• In if…else statement, if condition is true then statements in if block
will be executed but if it comes out as false then else block will be
executed.
• Syntax: Flowchart:
if (condition)
{
// Executes this block if
// condition is true
}
else
{
// Executes this block if
// condition is false
}
// Java program to illustrate if-else statement
class IfElseDemo
{
public static void main(String args[])
{
int i = 10;
if (i < 15)
System.out.println("i is smaller than 15");
else
System.out.println("i is greater than 15");
}
}
Output:
i is smaller than 15
if-else-if ladder:
• A user can decide among multiple options.
• The if statements are executed from the top down.
• As soon as one of the conditions controlling the if is true, the
statement associated with that if is executed, and the rest of the
ladder is bypassed.
• If none of the conditions is true, then the final else statement will be
executed.
Syntax:
if (condition)
statement;
else if (condition)
statement;
.
.
else
statement;
// Java program to illustrate if-else-if ladder
class ifelseifDemo
{
public static void main(String args[])
{
int i = 20;
if (i == 10)
System.out.println("i is 10");
else if (i == 15)
System.out.println("i is 15");
else if (i == 20)
System.out.println("i is 20");
else
System.out.println("i is not present");
}
}
Output:
i is 20
nested-if:
• Nested if statements means an if statement inside an if statement i.e,
we can place an if statement inside another if statement.
Syntax:
if (condition1)
{
// Executes when condition1 is true
if (condition2)
{
// Executes when condition2 is true
}
else
{
// Executes when condition2 is false
}
}
else
{
// Executes when condition1 is false
}
switch-case:
• The switch statement is a multiway branch statement.
Syntax:
switch (expression)
{
case value1:
statement1;
break;
case value2:
statement2;
break;
.
.
case valueN:
statementN;
break;
default:
statementDefault;
}
// Java program to illustrate switch-case
class SwitchCaseDemo
{
public static void main(String args[])
{
int i = 9;
switch (i)
{
case 0:
System.out.println("i is zero.");
break;
case 1:
System.out.println("i is one.");
break;
case 2:
System.out.println("i is two.");
break;
default:
System.out.println("i is greater than 2.");
}
}
}
Output:
i is greater than 2.
Looping Statements
• Looping in programming languages is a feature which facilitates the
execution of a set of instructions/functions repeatedly while some
condition evaluates to true.
• while
• do-while
• for
while loop:
• A while loop is a control flow statement that allows code to be executed
repeatedly based on a given Boolean condition.
• While loop starts with the checking of condition. If it evaluated to true, then the
loop body statements are executed otherwise first statement following the loop is
executed. For this reason it is also called Entry control loop
Syntax :
while (boolean
condition)
{
loop statements...
};
// Java program to illustrate while loop
class whileLoopDemo
{
public static void main(String args[])
{
int x = 1;
x++;
}
}
}
Output:
Value of x:1
Value of x:2
Value of x:3
Value of x:4
do while:
• do while loop is similar to while loop with only difference that it
checks for condition after executing the statements, and therefore is
an example of Exit Control Loop.
• do while loop starts with the execution of the statement(s). There is
no checking of any condition for the first time.
Syntax:
do
{
statements..
}
while (condition);
// Java program to illustrate do-while loop
class dowhileloopDemo
{
public static void main(String args[])
{
int x = 21;
do
{
// The line will be printed even
// if the condition is false
System.out.println("Value of x:" + x);
x++;
}
while (x < 20);
}
}
Output:
Value of x: 21
for loop:
• for loop provides a concise way of writing the loop structure. Unlike a
while loop, a for statement consumes the initialization, condition and
increment/decrement in one line.
Syntax:
for (initialization condition;
testing condition;
increment/decrement)
{
statement(s)
}
/ Java program to illustrate for loop.
class forLoopDemo
{
public static void main(String args[])
{
// for loop begins when x=2
// and runs till x <=4
for (int x = 2; x <= 4; x++)
System.out.println("Value of x:" + x);
}
}
Output:
Value of x:2
Value of x:3
Value of x:4
Difference between break and continue
statement
• The break keyword is used to breaks(stopping) a loop execution,
which may be a for loop, while loop, do while.
• The continue keyword is used to skip the particular recursion only in a
loop execution, which may be a for loop, while loop, do while.
Example: Program Output:
class BreakAndContinue
{
public static void main(String args[]) Break Statement
{ ....................
// Illustrating break statement (execution stops when value of i 1
becomes to 4.) 2
System.out.println("Break Statement\n...................."); 3
for(int i=1;i<=5;i++) Continue Statement
{
if(i==4) break;
....................
System.out.println(i); 1
} 2
3
// Illustrating continue statement (execution skipped when value of 5
i becomes to 1.)
System.out.println("Continue Statement\n....................");
for(int i=1;i<=5;i++)
{
if(i==4) continue;
System.out.println(i);
}
}
}
Data types in Java
• Every variable in Java has a data type which tells the compiler what
type of variable it as and what type of data it is going to store.
• Data type specifies the size and type of values.
• Information is stored in computer memory with different data types.
• Whenever a variable is declared, it becomes necessary to define a
data type that what will be the type of data that variable can hold.
Primary Data Type
• Java supports eight primitive datatypes:
• byte, short, int, long, float, double, char and boolean.
• These eight data types are further classified into four groups:
• Integer,
• Relational Numbers(Floating point)
• Characters
• Boolean(Conditional).
Intergers
• Integer is the whole number without any fractional point. It can hold
whole numbers such as 196, -52, 4036, etc.
• Java supports four different types of integers, these are:
Type Width Range
byte 8 bit or -128 to 127
1 byte
short 16 bit or -32,768 to 32767
2 bytes
int 32 bit or -2147,483,648 to 2147,483,647
4 bytes
Declaration:
data_type[][] array_name = new data_type[x][y];
For example: int arr[][] = new int[10][20];
• Size of multidimensional arrays: The total number of elements that can be stored
in a multidimensional array can be calculated by multiplying the size of all the
dimensions.
• For example:
The array int[][] x = new int[10][20] can store a total of (10*20) = 200 elements.
Representation of 2D array in Tabular Format:
• A two – dimensional array can be seen as a table with ‘x’ rows and ‘y’
columns where the row number ranges from 0 to (x-1) and column
number ranges from 0 to (y-1). A two – dimensional array ‘x’ with 3
rows and 3 columns is shown below:
Example 1:
Example 2:
class TwoDArray
class GFG {
{
public static void main(String[] args)
public static void main(String[] args)
{
{
int[][] arr = { { 1, 2 }, { 3, 4 } };
int[][] arr = new int[10][20];
arr[0][0] = 1;
System.out.println("arr[0][0] = " + arr[0][0]);
}
System.out.println("arr[0][0] = " + arr[0][0]);
}
}
}
Output:
Output:
arr[0][0] = 1
arr[0][0] = 1
class TwoDArray
{
Output:
public static void main(String[] args)
{ 0 1
2 3
int arr[][] = new int[4][5];
int i,j,k=0;
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
{
arr[i][j]=k;
k++;
}
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
{
system.out.println(arr[i][j]+” ”);
system.out.println();
}
}
}
Strings
• String defines an object.
• String type is used to declare string variables.
• Example:
String str=“ this is a sample string”;
System.out.println(str);
Operators: Example:
public class operators
{
public static void main(String[] args)
{
Arithmetic Operators: int a = 20, b = 10, d = 20, e = 40, f = 30;
System.out.println("a + b = " + (a + b));
They are used to perform simple arithmetic System.out.println("a - b = " + (a - b));
operations on primitive data types. System.out.println("a * b = " + (a * b));
* : Multiplication System.out.println("a / b = " + (a / b));
/ : Division System.out.println("a % b = " + (a % b));
% : Modulo
+ : Addition }
– : Subtraction }
Output:
a + b = 30
a - b = 10
a * b = 200
a/b=2
a%b=0
Arithmetic Compound Assignment
Statements
• Assignment operators are used to assign values to variables.
• In the example below, we use the assignment operator (=) to assign
the value 10 to a variable called x:
• int x = 10;
• In many cases assignment operator can be combined with other
operators to build a shorter version of statement called Compound
Statement.
• For example, instead of a = a+5, we can write a += 5.
Increment and Decrement Operator
++ :Increment operator, used for incrementing the value by 1.
• There are two varieties of increment operator.
• Post-Increment : Value is first used for computing the result and then
incremented.
• Pre-Increment : Value is incremented first and then result is computed.
-- : Decrement operator, used for decrementing the value by 1.
• There are two varieties of decrement operator.
• Post-decrement : Value is first used for computing the result and then
decremented.
• Pre-Decrement : Value is decremented first and then result is computed.
Example: Output:
class operators
{
public static void main(String[] args)
{
int a = 20, b = 10, c = 0, d = 20, e = 40;
boolean condition = true;
c = ++a;
System.out.println("Value of c (++a) = " + c); Value of c (++a) = 21
c = b++;
System.out.println("Value of c (b++) = " + c); Value of c (b++) = 10
c = --d;
System.out.println("Value of c (--d) = " + c); Value of c (--d) = 19
c = e--;
System.out.println("Value of c (e--) = " + c); Value of c (e--) = 40
}
}
Bitwise Operators :
• These operators are used to perform manipulation of individual bits
of a number. They can be used with any of the integer types.
• &, Bitwise AND operator: returns bit by bit AND of input values.
• |, Bitwise OR operator: returns bit by bit OR of input values.
• ^, Bitwise XOR operator: returns bit by bit XOR of input values.
• ~, Bitwise Complement Operator: This is a unary operator which
returns the one’s compliment representation of the input value, i.e.
with all bits inversed.
Bitwise OR (|) –
• This operator is binary operator, denoted by ‘|’.
• It returns bit by bit OR of input values, i.e, if either of the bits is 1, it
gives 1, else it gives 0.
For example,
a = 5 = 0101 (In Binary)
b = 7 = 0111 (In Binary)
~ 0101
________
1010 = 10 (In decimal)
Example: Output :
public class operators
{
public static void main(String[] args)
{
int a = 5;
int b = 7;
// bitwise or a|b = 7
// 0101 | 0111=0111 = 7
System.out.println("a|b = " + (a | b));
// bitwise xor
// 0101 ^ 0111=0010 = 2 a^b = 2
System.out.println("a^b = " + (a ^ b));
}
}
Shift Operators:
• These operators are used to shift the bits of a number left or right
thereby multiplying or dividing the number by two respectively.
• They can be used when we have to multiply or divide a number by
two.
General format:
• number shift_op number_of_places_to_shift;
Signed Right shift operator (>>) –
• Shifts the bits of the number to the right.
• The leftmost bit depends on the sign of initial number.
• Similar effect as of dividing the number with some power of two.
For example,
Example 1:
a = 10
a>>1 = 5
Example 2:
a = -10
a>>1 = -5
We preserve the sign bit.
Unsigned Right shift operator (>>>) –
• Shifts the bits of the number to the right and fills 0 on voids left as a
result.
• The leftmost bit is set to 0. (>>>) is unsigned-shift; it’ll insert 0. (>>) is
signed, and will extend the sign bit.
For example,
Example 1:
a = 10
a>>>1 = 5
Example 2:
a = -10
a>>>1 = 2147483643
DOES NOT preserve the sign bit.
Left shift operator (<<) –
• Shifts the bits of the number to the left and fills 0 on voids left as a
result.
• Similar effect as of multiplying the number with some power of two.
For example,
a = 5 = 0000 0101
b = -10 = 1111 0110
}
}
Logical Operators :
• These operators are used to perform “logical AND” and “logical OR”
operation, i.e. the function similar to AND gate and OR gate in digital
electronics.
• One thing to keep in mind is the second condition is not evaluated if
the first one is false, i.e. it has a short-circuiting effect.
• Used extensively to test for several conditions for making a decision.
• Conditional operators are
• -&&, Logical AND : returns true when both conditions are true.
• ||, Logical OR : returns true if at least one condition is true.
Ternary operator : (?: )
• Ternary operator is a shorthand version of if-else statement.
• It has three operands and hence the name ternary.
• General format is-
• Exp1?Exp2:Exp3
• condition ? if true : if false
• The above statement means that if the condition evaluates to true,
then execute the statements after the ‘?’ else execute the statements
after the ‘:’.
Module 3
• A class creates a new data type that can be used to create objects.
• That is, a class creates a logical framework that defines the
relationship between its members.
• When you declare an object of a class, you are creating an instance of
that class.
• Thus,a class is a logical construct.
• An object has physical reality. (That is, an object occupies space in
memory.)
Assigning Object Reference Variables
• Box b1 = new Box();
• Box b2 = b1;
• When you assign one object reference variable to another object
reference variable, you are not creating a copy of the object, you are
only making a copy of the reference.
Introducing Methods
• This is the general form of a method:
type name(parameter-list)
{
// body of method
}
Returning a Value
• There are two important things to understand about returning values:
• The type of data returned by a method must be compatible with the
return type specified by the method. For example, if the return type
of some method is boolean, you could not return an integer.
• The variable receiving the value returned by a method(such as vol, in
this case)must also be compatible with the return type specified for
the method.
Adding a Method That Takes Parameters
• While some methods don’t need parameters, most do.
• A very simple example of method without parameters .
int square()
{
return 10 * 10;
}
• if you modify the method so that it takes a parameter, as shown next,
int square(int i)
{
return i * i;
}
int x, y;
x = square(5); // x equals 25
x = square(9); // x equals 81
y = 2;
x = square(y); // x equals 4
Constructors
• It can be tedious to initialize all of the variables in a class each time an
instance is created.
• Java allows objects to initialize themselves when they are created.
• This automatic initialization is performed through the use of a constructor.
• It has the same name as the class in which it resides and is syntactically
similar to a method.
• Constructors they have no return type, not even void.
• Once defined, the constructor is automatically called immediately after the
object is created, before the new operator completes.
• A constructor initializes an object immediately upon creation.
Types of constructor
There are two types of constructor in Java:
• Default constructor :
• If we don’t define a constructor in a class, then compiler creates for
the class.
• Default constructor provides the default values to the object like 0,
null, etc. depending on the type.
• And if we write a constructor with arguments or no-arguments then
the compiler does not create a default constructor.
Parameterized Constructor:
• A constructor that has parameters is known as parameterized
constructor.
• If we want to initialize fields of the class with your own values, then
use a parameterized constructor.
The this Keyword
• this can be used inside any method to refer to the current object.
• ‘this’ is a reference variable that refers to the current object.
• Instance Variable Hiding:
Example:
class Test
{
int a;
int b;
Test(int a, int b)
{
this.a = a;
this.b = b;
} Output:
a = 10 b = 20
void display()
{
System.out.println("a = " + a + " b = " + b);
}
Syntax :
class derived-class extends base-class
{
//methods and fields
}
}
// A's j is not accessible here.
class B extends A {
int total;
void sum() {
total = i + j; // ERROR, j is not accessible here
}
}
A More Practical Example
// This program uses inheritance to extend Box. // Here, Box is extended to include weight.
class Box class BoxWeight extends Box
{ {
double width; double weight; // weight of box
double height; // constructor for BoxWeight
double depth; BoxWeight(double w, double h, double
// constructor used when all dimensions specified d, double m)
Box(double w, double h, double d) {
{ width = w;
width = w; height = h;
height = h; depth = d;
depth = d; weight = m;
} }
// compute and return volume }
double volume()
{
return width * height * depth;
}
}
class DemoBoxWeight
{
public static void main(String args[])
{
BoxWeight mybox1 = new BoxWeight(10, 20, 15, 34.3);
BoxWeight mybox2 = new BoxWeight(2, 3, 4, 0.076);
double vol;
vol = mybox1.volume();
System.out.println("Volume of mybox1 is " + vol);
System.out.println("Weight of mybox1 is " + mybox1.weight);
System.out.println();
vol = mybox2.volume();
System.out.println("Volume of mybox2 is " + vol);
System.out.println("Weight of mybox2 is " + mybox2.weight);
}
}
A Superclass Variable Can Reference a Subclass
Object
• A reference variable of a superclass can be assigned a reference to
any subclass derived from that superclass.
• when a reference to a subclass object is assigned to a superclass
reference variable, you will have access only to those parts of the
object defined by the superclass.
class RefDemo
{
public static void main(String args[])
{
BoxWeight weightbox = new BoxWeight(3, 5, 7, 8.37);
Box plainbox = new Box();
double vol;
vol = weightbox.volume();
System.out.println("Volume of weightbox is " + vol);
System.out.println("Weight of weightbox is " +weightbox.weight);
System.out.println();
/* The following statement is invalid because plainbox does not define a weight member. */
// System.out.println("Weight of plainbox is " + plainbox.weight);
}
}
Using super
• The super keyword refers to superclass (parent) objects.
• The most common use of the super keyword is to eliminate the
confusion between superclasses and subclasses that have methods
with the same name.
• super is used to invoke parent class constructor.
• super can be used to invoke parent class method
• super is used to refer immediate parent class instance variable.
Let’s review the key concepts behind super( )
Process-based Thread-based
• Messaging : After you divide your program into separate threads, you need to
define how they will communicate with each other.
• When programming with most other languages, you must depend on the operating
system to establish communication between threads. This, of course, adds overhead.
• By contrast, Java provides a clean, low-cost way for two or more threads to talk to
each other, via calls to predefined methods that all objects have.
• Java’s messaging system allows a thread to enter a synchronized method on an object,
and then wait there until some other thread explicitly notifies it to come out.
The Thread Class and the Runnable Interface
• Java’s multithreading system is built upon the Thread class, its methods, and its
companion interface, Runnable.
• Thread encapsulates a thread of execution.
• Since you can’t directly refer to the ethereal state of a running thread, you will deal
with it through its proxy, the Thread instance that spawned it.
• To create a new thread, your program will either extend Thread or implement the
Runnable interface.
• The Thread class defines several methods that help manage threads.
The Main Thread
• When a Java program starts up, one thread begins running immediately.
• This is usually called the main thread of your program, because it is the one that is
executed when your program begins.
• The main thread is important for two reasons:
• It is the thread from which other “child” threads will be spawned.
• Often, it must be the last thread to finish execution because it performs various
shutdown actions.
• Although the main thread is created automatically when your program is started, it can
be controlled through a Thread object.
• To do so, you must obtain a reference to it by calling the method currentThread( ),
which is a public static member of Thread.
• Its general form is shown here:
static Thread currentThread( )
• This method returns a reference to the thread in which it is called. Once you have a
reference to the main thread, you can control it just like any other thread.
Example
// Controlling the main Thread.
class CurrentThreadDemo
{
public static void main(String args[ ]) {
Thread t = Thread.currentThread( );
System.out.println("Current thread: " + t);
// change the name of the thread In this program, a reference to
t.setName("My Thread"); the current thread (the main
System.out.println("After name change: " + t); thread, in this case) is
try { obtained by calling
for(int n = 5; n > 0; n--) currentThread( ), and this
{ reference is stored in the local
System.out.println(n); variable t.
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted");
}
}
}
Contd….
• In this program, a reference to the current thread (the main thread, in this case) is
obtained by calling currentThread( ), and this reference is stored in the local
variable t.
• The program then calls setName( ) to change the internal name of the thread.
Information about the thread is then redisplayed.
• Next, a loop counts down from five, pausing one second between each line. The pause
is accomplished by the sleep( ) method.
• The argument to sleep( ) specifies the delay period in milliseconds. Notice the
try/catch block around this loop.
• The sleep( ) method in Thread might throw an InterruptedException.
• This would happen if some other thread wanted to interrupt this sleeping one. This
example just prints a message if it gets interrupted.
• In a real program, you would need to handle this differently. Here is the output
generated by this program:
• After the new thread is created, it will not start running until you call its start( )
method, which is declared within Thread.
• In essence, start( ) executes a call to run( ). The start( ) method is shown here:
void start( )
Programs
// Create a second thread.
class NewThread implements Runnable
{
Thread t; class ThreadDemo
NewThread( ) {
{
public static void main(String args[])
// Create a new, second thread
t = new Thread(this, "Demo Thread"); {
System.out.println("Child thread: " + t); new NewThread( ); // create a new thread
t.start(); // Start the thread try {
} for(int i = 5; i > 0; i--) {
// This is the entry point for the second thread. System.out.println("Main Thread: " + i);
public void run( ) Thread.sleep(1000);
{
}
try {
for(int i = 5; i > 0; i--) } catch (InterruptedException e)
{ {System.out.println("Main thread
System.out.println("Child Thread: " + i); interrupted.");
Thread.sleep(500); }
} System.out.println("Main thread exiting.");
} catch (InterruptedException e) { }
System.out.println("Child interrupted.");
}
}
System.out.println("Exiting child thread.");
}
}
Contd…
• Inside NewThread’s constructor, a new Thread object is created by the following
statement:
t = new Thread(this, "Demo Thread");
• Passing this as the first argument indicates that you want the new thread to call
the run( ) method on this object.
• Next, start( ) is called, which starts the thread of execution beginning at the
run( ) method.
• This causes the child thread’s for loop to begin. After calling start( ), NewThread’s
constructor returns to main( ).
• When the main thread resumes, it enters its for loop. Both threads continue running,
sharing the CPU, until their loops finish.
• In fact, for some older JVMs, if the main thread finishes before a child thread has
completed, then the Java run-time system may “hang.”
• The preceding program ensures that the main thread finishes last, because the main
thread sleeps for 1,000 milliseconds between iterations, but the child thread sleeps for
only 500 milliseconds.
• This causes the child thread to terminate earlier than the main thread.
Contd…
• 2) Extending Thread: The second way to create a thread is to create a new class
that extends Thread, and then to create an instance of that class.
• The extending class must override the run( ) method, which is the entry point for the
new thread.
• It must also call start( ) to begin execution of the new thread. Here is the preceding
program rewritten to extend Thread:
PROGRAM
• This program generates the same output as the preceding version. As you can see, the
child thread is created by instantiating an object of NewThread, which is derived
from Thread.
• Notice the call to super( ) inside NewThread. This invokes the following form of
the Thread constructor:
public Thread(String threadName)
• Here, threadName specifies the name of the thread.
Choosing an Approach
• At this point, you might be wondering why Java has two ways to create child threads,
and which approach is better.
• The answers to these questions turn on the same point. The Thread class defines
several methods that can be overridden by a derived class.
• Of these methods, the only one that must be overridden is run( ).
• This is, of course, the same method required when you implement Runnable.
• Many Java programmers feel that classes should be extended only when they are
being enhanced or modified in some way.
• So, if you will not be overriding any of Thread’s other methods, it is probably best
simply to implement Runnable.
Creating Multiple Threads
• So far, you have been using only two threads: the main thread and one child thread.
However, your program can spawn as many threads as it needs.
// Create multiple threads.
class NewThread implements Runnable
{
String name; // name of thread
Thread t;
class MultiThreadDemo
NewThread(String threadname) { {
name = threadname; public static void main(String args[ ]) {
t = new Thread(this, name); new NewThread("One"); // start threads
System.out.println("New thread: " + t); new NewThread("Two");
t.start(); // Start the thread new NewThread("Three");
} try {
// This is the entry point for thread.
public void run( ) {
// wait for other threads to end
Try { Thread.sleep(10000);
for(int i = 5; i > 0; i--) { } catch (InterruptedException e) {
System.out.println(name + ": " + i); System.out.println("Main thread Interrupted");
Thread.sleep(1000); }
} System.out.println("Main thread exiting.");
} catch (InterruptedException e) { }
System.out.println(name + "Interrupted");
}
}
System.out.println(name + " exiting.");
}
}
Using isAlive( ) and join( )
• As mentioned, often you will want the main thread to finish last. In the preceding
examples, this is accomplished by calling sleep( ) within main( ), with a long
enough delay to ensure that all child threads terminate prior to the main thread.
• However, this is hardly a satisfactory solution, and it also raises a larger question:
• How can one thread know when another thread has ended?
• Two ways exist to determine whether a thread has finished.
• First, you can call isAlive( ) on the thread.
• Second, more commonly use to wait for a thread to finish is called join( ).
True
General form of isAlive( ) : final boolean isAlive( )
False
The isAlive( ) method returns true if the thread upon which it is called is still
running.
• Returns false otherwise.
Contd…
• While isAlive( ) is occasionally useful.
join()------------→ final void join( ) throws InterruptedException
PROGRAM
As you can see, after the calls to join( ) return, the threads have stopped executing.
Thread Priorities
• Thread priorities are used by the thread scheduler to decide when each thread should
be allowed to run.
• Higher-priority threads get more CPU time than lower-priority threads.
• A higher-priority thread can also preempt a lower-priority one.
• For instance, when a lower-priority thread is running and a higher-priority thread
resumes, it will preempt the lower priority thread.
• To set a thread’s priority, use the setPriority( ) method, which is a member of Thread.
final void setPriority(int level)
Level: MIN_PRIORITY (1)
NORM_PRIORITY (5) (Default)
MAX_PRIORITY (10)
You can obtain the current priority setting by calling the getPriority( ) method of
Thread.
final int getPriority( )
• In theory, threads of equal priority should get equal access to the CPU. But you need
to be careful.
Contd…
• Remember, Java is designed to work in a wide range of environments. Some of
those environments implement multitasking fundamentally differently than others.
• For safety, threads that share the same priority should yield control once in a while.
• This ensures that all threads have a chance to run under a non-preemptive operating
system.
• In practice, even in non-preemptive environments, most threads still get a chance to
run, because most threads inevitably encounter some blocking situation, such as
waiting for I/O.
• When this happens, the blocked thread is suspended and other threads can run. But,
if you want smooth multithreaded execution, you are better off not relying on this.
• Also, some types of tasks are CPU-intensive. Such threads dominate the CPU. For
these types of threads, you want to yield control occasionally so that other threads
can run.
• Implementations of Java may have radically different behavior when it comes to
scheduling.
• Most of the inconsistencies arise when you have threads that are relying on
preemptive behavior, instead of cooperatively giving up CPU time.
Contd….
• The safest way to obtain predictable, cross-platform behavior with Java is to use
threads that voluntarily give up control of the CPU.
• The following example demonstrates two threads at different priorities, which do not
run on a preemptive platform in the same way as they run on a nonpreemptive
platform.
• One thread is set two levels above the normal priority, as defined by
Thread.NORM_PRIORITY, and the other is set to two levels below it.
• The threads are started and allowed to run for ten seconds. Each thread executes a
loop, counting the number of iterations. After ten seconds, the main thread stops both
threads.
•PROGRAM
One other note about the preceding program. Notice that running is
preceded by the keyword volatile.
while (running) {
click++;
}
• Without the use of volatile, Java is free to optimize the loop in such a way that a
local copy of running is created.
Synchronization
• When two or more threads need access to a shared resource, they need some way to
ensure that the resource will be used by only one thread at a time.
• The process by which this is achieved is called synchronization. As you will see, Java
provides unique, language-level support for it.
• Key to synchronization is the concept of the monitor (also called a semaphore). A
monitor is an object that is used as a mutually exclusive lock, or mutex.
• Only one thread can own a monitor at a given time. When a thread acquires a lock, it
is said to have entered the monitor.
• All other threads attempting to enter the locked monitor will be suspended until the
first thread exits the monitor.
• These other threads are said to be waiting for the monitor. A thread that owns a
monitor can reenter the same monitor if it so desires.
• If you have worked with synchronization when using other languages, such as C or
C++, you know that it can be a bit tricky to use.
• This is because these languages do not, themselves support synchronization.
• Because other languages need operating system primitives for synchronization, But in
java synchronization doesn’t need operating system primitives.
Contd…
• Java implements synchronization through language elements, most of the complexity
associated with synchronization has been eliminated.
• You can synchronize your code in either of two ways. Both involve the use of the
synchronized keyword.
• Using Synchronized Methods: Synchronization is easy in Java, because
all objects have their own implicit monitor associated with them.
• To enter an object’s monitor, just call a method that has been modified with the
synchronized keyword
• While a thread is inside a synchronized method, all other threads that try to call it (or
any other synchronized method) on the same instance have to wait.
• To exit the monitor and relinquish control of the object to the next waiting thread, the
owner of the monitor simply returns from the synchronized method.
EXAMPLE
• The following program has three simple classes. The first one, Callme, has a single
method named call( ). The call( ) method takes a String parameter called msg. This
method tries to print the msg string inside of square brackets. The interesting thing
to notice is that after call( ) prints the opening bracket and the msg string, it calls
Thread .sleep(1000), which pauses the current thread for one second.
Contd…
• The constructor of the next class, Caller, takes a reference to an instance of the
Callme class and a String, which are stored in target and msg, respectively.
• The constructor also creates a new thread that will call this object’s run( ) method.
The thread is started immediately. The run( ) method of Caller calls the call( )
method on the target instance of Callme, passing in the msg string.
• As you can see, by calling sleep( ), the call( ) method allows execution to switch to
another thread.
• This results in the mixed-up output of the three message strings.
• In this program, nothing exists to stop all three threads from calling the same method,
on the same object, at the same time.
• This is known as a race condition, because the three threads are racing each other to
complete the method. This example used sleep( ) to make the effects repeatable and
obvious.
• In most situations, a race condition is more subtle and less predictable, because you
can’t be sure when the context switch will occur. This can cause a program to run
right one time and wrong the next.
• To fix the preceding program, you must serialize access to call( ).
Example
class Callme
{
synchronized void call(String msg)
{
...
synchronized has been added to call( ), the output of the program is as follows:
• [Hello]
• [Synchronized]
• [World]
• Any time that you have a method, or group of methods, that manipulates the internal
state of an object in a multithreaded situation, you should use the synchronized
keyword to guard the state from race conditions.
• For example, consider the classic queuing problem, where one thread is producing
some data and another is consuming it.
• suppose that the producer has to wait until the consumer is finished before it generates
more data. In a polling system, the consumer would waste many CPU cycles while it
waited for the producer to produce.
• Once the producer was finished, it would start polling, wasting more CPU cycles waiting
for the consumer to finish, and so on.
• Clearly, this situation is undesirable.
Contd….
• These methods are implemented as final methods in Object, so all classes have
them.
• All three methods can be called only from within a synchronized context.
• wait( ) tells the calling thread to give up the monitor and go to sleep until some
other thread enters the same monitor and calls notify( ).
• notify( ) wakes up a thread that called wait( ) on the same object.
• notifyAll( ) wakes up all the threads that called wait( ) on the same object. One of
the threads will be granted access.
• These methods are declared within Object, as shown here:
• final void wait( ) throws InterruptedException
• final void notify( )
• final void notifyAll( )
Producer-Consumer Problem
Contd…
Producer-Consumer Program
Contd…
Example
Contd…
Deadlock
Deadlock
• Deadlock describes a situation where two or more threads are blocked forever, waiting for
each other.
• Deadlocks can occur in Java when the synchronized keyword causes the executing thread to
block while waiting to get the lock, associated with the specified object.
• Since the thread might already hold locks associated with other objects, two threads
could each be waiting for the other to release a lock. In such case, they will end up
waiting forever.
Suspending, resuming and stopping threads
• Prior to Java 2, a program used suspend( ) and resume( ), which are methods defined
by
• Thread, to pause and restart the execution of a thread.
• They have the form shown below:
• final void suspend( )
• final void resume( )
• The Thread class also defines a method called stop( ) that stops a thread
• final void stop( )
• Once a thread has been stopped, it cannot be restarted using resume( ).
Contd…
Events are s u p p o r t e d b y a n u m b e r o f
packages, including java.util, java.awt, a n d
java.awt.event.
T h e m o d e r n approach t o handling e v e n t s is
b a s e d o n t h e delegation event model, which
defines standard and consistent m e c h a n i s m s
t o generate and process events.
Its c o n c e pt is quite simple:
a source generates an e v e n t and s e n d s it t o
o n e or m o re listeners
In this s c h e m e , t h e listener simply waits until
it receives an event. Once an e v e n t is
received, t h e listener p ro ce sses t h e e v e n t and
t h e n returns.
Even t s
In t h e delegation m o d e l , an event is an object
that describes a state change in a source. It
can b e generated as a c o n s e q u e n c e o f a
p e r s o n interacting with t h e e l e m e n t s in a
graphical user interface.
Second, it m u s t i m p l e m e n t m e t h o d s t o
receive a n d process t h e s e notifications.
Event Classes
Th e m o s t widely u s e d e v e n t s are t h o s e
defined b y t h e AWT.
At t h e root o f t h e Java e v e n t class hierarchy is
EventObject, which is in java.util.
It is t h e superclass for all events. Its o n e
constructor is s h o w n here:
EventObject(Object src )
To s u mma r i z e :
EventObject is a superclass o f all events.
AWTEvent is a superclass o f all AWT e v e n t s
that are handled b y t h e delegation e v ent
model.
Th e package java.awt.event defines m a n y
t y p e s o f e v e n t s that are generated b y various
user interface e l e m e n t s
Th e AdjustmentEvent Class
A ComponentEvent is generated w h e n t h e
size, position, or visibility o f a c o m p o n e n t is
changed.
There are four t y p e s o f c o m p o n e n t events.
AContainerEvent is generated w h e n a c o m p o n e n t is
a d d e d t o or re m o v e d f ro m a container.
There are t w o t y p e s o f container events. T h e
ContainerEvent class defines int constants that can b e
u s e d t o identify t h e m : COMPONENT_ADDED and
COMPONENT_REMOVED.
T h e t y p e o f t h e e v e n t is specified b y type,
a n d t h e c o m p o n e n t that has b e e n a d d e d t o or
re m o v e d f ro m t h e container is comp
Th e FocusEvent Class
AFocusEvent is generated w h e n a c o m p o n e n t
gains or loses input focus.
T h e a rg u m e n t temporaryFlag is s e t t o true if
t h e f o cus e v ent is temporary. Otherwise, it is
s e t t o false.
T h e ItemEvent Class
An ItemEvent is generated w h e n a c h e c k b o x
or a list i t e m is clicked or w h e n a checkable
m e n u i t e m is selected or deselected.
T h e t y p e o f t h e e v e n t is specified b y type.
void actionPerformed(ActionEvent ae )
Th e AdjustmentListener Interface.
void
adjustmentValueChanged(AdjustmentEvent
ae )
Th e ComponentListener Interface
void componentAdded(ContainerEvent ce )
void componentRemoved(ContainerEvent ce )
Java provides a special feature, called an
adapter class, that can simplify t h e creation
o f e v e n t handlers in certain situations.
An adapter class provides an e m p t y
implementation o f all m e t h o d s in an
eve nt listener interface.
Adapter classes are useful w h e n yo u want to
receive and process only s o m e o f t h e eve nt s
that are handled by a particular eve nt listener
interface.
You can define a n e w class t o act as an event
listener by e x t e n d i n g o n e of t h e adapter classes
and i mp l emen t i n g only t h o s e event s in which you
are interested.
T he e m p t y implement at i on of mouseMoved( )
would handle t h e m o u s e m o t i o n event s for you.
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
/*
<applet code="AdapterDemo" w i d t h = 3 0 0
height=100>
</applet>
*/
public class AdapterDemo e x t e n d s Applet {
public void init() {
addMouseListener(new MyMouseAdapter(this));
addMouseMotionListener(new
MyMouseMotionAdapter(this));
}
}
class MyMouseAdapter e x t e n d s MouseAdapter
{
Adapter D em o adapterDemo;
public MyMouseAdapter(AdapterDemo adapterDemo) {
this.adapterDemo = adapterDemo;
}
/ / Handle m o u s e clicked.
public void mouseClicked(MouseEvent m e )
{
adapterDemo.showStatus("Mouse clicked");
}
}
class MyMouseMotionAdapter e x t e n d s
MouseMotionAdapter {
Adapter D em o adapterDemo;
public MyMouseMotionAdapter(AdapterDemo
adapterDemo) {
this.adapterDemo = adapterDemo;
}
/ / Handle m o u s e dragged.
In general, a visual c o m p o n e n t is a c o m p o s i t e of
three distinct aspects:
• T he way that t h e c o m p o n e n t looks w h e n
rendered o n t h e screen
• T h e way that t h e c o m p o n e n t reacts t o t h e user
• T h e state information associated with
the component
Th e MVC architecture is successful b e cause
each piece o f t h e d esign corresponds t o an
aspect o f a c o m p o n e n t .
For e x a m p l e , in t h e case o f a c h e c k b o x , t h e
m o d e l contains a field that indicates if t h e
b o x is c h e c k e d or u n c h e c k e d .
T h e view d e t e r mi n e s h o w t h e c o m p o n e n t is
displayed o n t h e screen, including any
aspects o f t h e view that are affected b y t h e
current state of t h e m o d e l .
Th e controller d e t e r mi n e s h o w t h e
c o m p o n e n t reacts t o t h e user.
T h e d iffe re n c e b e t w e e n t h e t w o is f o u n d in their
i n t e n d e d p u r p o se : A s t h e t e r m is c o m m o n l y u s e d , a
component is a n i n d e p e n d e n t visual control, s u c h a s
a p u s h b u t t o n or slider.
A container h o l d s a g r o u p o f c o m p o n e n t s . T h u s , a
container is a special t y p e o f c o m p o n e n t t h at is
designed to hold other component s .
Components
T h e s e c o n d t y p e of containers s u p p o r t e d b y
Swing are lightweight containers. Lightweight
containers do inherit JComponent
S w i n g - b a s e d applets are similar t o AW T-
b a s e d applets, b u t with an important
difference: A Swing applet e x t e n d s JApplet
rather than Applet.
setLayout(new FlowLayout());
/ / Make t w o b u t t o n s .
jbtnAlpha = n e w JButton("Alpha");
jbtnBeta = n e w JButton("Beta");
add(jbtnAlpha);
add(jbtnBeta);
/ / Create a t e x t - b a s e d label.
JLabel(Icon icon )
JLabel(String str )
JLabel(String str , Icon icon , int align )
Here, str and icon are t h e t e x t and icon u s e d
for t h e label.
import java.awt.*;
import javax.swing.*;
/*
<applet code="JLabelDemo" w i d t h = 2 5 0
height=150>
</applet>
*/
public class JLabelDemo e x t e n d s JApplet {
public void init() {
try {
SwingUtilities.invokeAndWait(new Runnable()
{
public void run() {
makeGUI();
}
}
);
JTextField(int cols )
JTextField(String str , int cols )
JTextField(String str )
Here, str is t h e string t o b e initially pres ented ,
and cols is t h e n u m b e r of c o l u m n s in t h e t e x t
field.
JButton(Icon icon )
JButton(String str )
JButton(String str , Icon icon )
Here, str an d icon are t h e string and icon u s e d
for t h e b u t t o n . When t h e b u t t o n is pressed, an
ActionEvent is generated .
A useful variation o n t h e p u s h b u t t o n is called a
toggle button .
JRadioButton(String str )
JList(Object[ ] items )
T h e JComboBox constructor u s e d b y t h e e x a m p l e is
s h o w n here:
JComboBox(Object[ ] items )
JTree(Object obj [ ])
JTree(Vector<?> v)
JTree(TreeNode tn )
JTable is a c o m p o n e n t that displays rows and
c o l u m n s o f data. You can drag t h e cursor o n
c o l u m n boundaries t o resize c o l u mn s . You
can also drag a c o l u m n t o a n e w position.