0% found this document useful (0 votes)
14 views128 pages

OOP and Advanc

Uploaded by

Lemi Biru
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views128 pages

OOP and Advanc

Uploaded by

Lemi Biru
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 128

METTU UNIVERSITY

COLLEGE OF ENGINEERING AND TECHNOLOGY

DEPARTMENT OF INFORMATION TECHNOLOGY

Exit Exam Module on Object Oriented Programming in Java And

Advanced Programming

December 19, 2024,


Mattu University
METTU UNIVERSITY

COLLEGE OF ENGINEERING AND TECHNOLOGY

DEPARTMENT OF INFORMATION TECHNOLOGY

Exit Exam Module on Object Oriented Programming in Java And

Advanced Programming

Prepared By:
1. Mr. Oliyad Seboka (MSc.)
2. Mr. Teshome Debushe (MSc.)

Reviewer 1: Mr. Kumara Chala (MSc.)

Reviewer 2: Mr. Hunde Yigazu (MSc.)

i
Table of Contents
List of Figure ................................................................................................................................................. iv
OBJECT ORIENTED PROGRAMMING IN JAVA ................................................................................................ v
CHAPTER ONE ............................................................................................................................................... 1
INTRODUCTION ............................................................................................................................................. 1
Java Features ............................................................................................................................................. 1
Structured vs Object-Oriented Programming ........................................................................................... 3
Java Applications ....................................................................................................................................... 4
Basic Syntax ............................................................................................................................................... 6
Java Identifiers .......................................................................................................................................... 6
Modifiers ................................................................................................................................................... 7
Data Types ................................................................................................................................................. 7
Java Variables .......................................................................................................................................... 10
Statements in Java .................................................................................................................................. 16
Java Arrays............................................................................................................................................... 33
Java Enums .............................................................................................................................................. 33
Review Questions .................................................................................................................................... 34
CHAPTER TWO ............................................................................................................................................ 35
BASIC OBJECT-ORIENTED CONCEPTS .......................................................................................................... 35
Classes and Objects ................................................................................................................................. 35
Difference between Class and Objects ................................................................................................... 44
Pillars of OOP in Java ............................................................................................................................... 45
Review Questions .................................................................................................................................... 52
ADVANCED PROGRAMMING....................................................................................................................... 54
Chapter One ................................................................................................................................................ 55
Array in Java ................................................................................................................................................ 55
Declaring an array in Java........................................................................................................................ 55
How to Initialize Arrays in Java ................................................................................................................ 56
Accessing Elements of an Array .............................................................................................................. 56
Multidimensional Arrays ......................................................................................................................... 60
Initializing a 2d array .............................................................................................................................. 61
Initializing a 3d array .............................................................................................................................. 65

ii
Review Questions .................................................................................................................................... 67
Chapter Two ................................................................................................................................................ 68
Java Exception ............................................................................................................................................. 68
Java Exception hierarchy ......................................................................................................................... 68
Errors ....................................................................................................................................................... 68
Exceptions ............................................................................................................................................... 69
Java Exception Types ............................................................................................................................... 69
Java Exception Handling .......................................................................................................................... 69
Review Questions .................................................................................................................................... 74
Chapter Three ............................................................................................................................................. 75
Multithreading in java ................................................................................................................................. 75
The Concept of Multitasking ................................................................................................................... 76
Thread Priority in Multithreading ........................................................................................................... 87
Naming a Thread ..................................................................................................................................... 93
Sleeping Thread .................................................................................................................................... 104
Thread Synchronization ........................................................................................................................ 110
Daemon Thread .................................................................................................................................... 117
Review Questions .................................................................................................................................. 122

iii
List of Figure
Figure 1: Types of Statements ..................................................................................................................... 16
Figure 2: Types of Statements in Java ......................................................................................................... 18
Figure 3: Java Objects.................................................................................................................................. 38
Figure 4: Java Object Declaration ................................................................................................................ 38
Figure 5: Memory Allocation of Java Objects.............................................................................................. 42
Figure 6:2-dimensional Array ...................................................................................................................... 61
Figure 7: Initialization of 2-dimensional Array ............................................................................................ 62
Figure 8: Threads in a Shared Memory Environment in OS ........................................................................ 75
Figure 9: Life Cycle of Thread ...................................................................................................................... 77

iv
OBJECT ORIENTED PROGRAMMING IN
JAVA

v
CHAPTER ONE
INTRODUCTION
Java is a popular high-level, object-oriented programming language that was originally developed by Sun
Microsystems and released in 1995. Currently, Java is owned by Oracle, and more than 3 billion devices
run Java. Java runs on a variety of platforms, such as Windows, Mac OS, and the various versions of
UNIX. Today Java is being used to develop numerous types of software applications, including desktop
apps, mobile apps, web apps, games, and much more.

Java is a general-purpose programming language intended to let programmers Write Once, Run Anywhere
(WORA). This means that compiled Java code can run on all platforms that support Java without the need
to recompile.

Java is known for its simplicity, robustness, and security features, making it a popular choice for
enterprise-level applications. Java applications are compiled to byte code that can run on any Java Virtual
Machine. The syntax of Java is similar to C/C++. Java makes writing, compiling, and debugging
programming easy. It helps to create reusable code and modular programs.

Java Features
1. Platform Independent

Compiler converts source code to byte code and then the JVM executes the bytecode generated by the
compiler. This byte code can run on any platform be it Windows, Linux, or macOS which means if we
compile a program on Windows, then we can run it on Linux and vice versa. Each operating system has
a different JVM, but the output produced by all the OS is the same after the execution of the byte code.
That is why we call java a platform-independent language.
1. Object-Oriented Programming

Java is an object-oriented language, promoting the use of objects and classes. Organizing the program in
the terms of a collection of objects is a way of object-oriented programming, each of which represents
an instance of the class.
The four main concepts of Object-Oriented programming are: Abstraction, Encapsulation, Inheritance
and Polymorphism
2. Simplicity

1
Java’s syntax is simple and easy to learn, especially for those familiar with C or C++. It eliminates
complex features like pointers and multiple inheritances, making it easier to write, debug, and maintain
code.
3. Robustness

Java language is robust which means reliable. It is developed in such a way that it puts a lot of effort into
checking errors as early as possible, that is why the java compiler is able to detect even those errors that
are not easy to detect by another programming language. The main features of java that make it robust
are garbage collection, exception handling, and memory allocation.
4. Security

In java, we don’t have pointers, so we cannot access out-of-bound arrays i.e it


shows ArrayIndexOutOfBound Exception if we try to do so. That’s why several security flaws like stack
corruption or buffer overflow are impossible to exploit in Java. Also, java programs run in an
environment that is independent of the os(operating system) environment which makes java programs
more secure.
5. Distributed

We can create distributed applications using the java programming language. Remote Method Invocation
and Enterprise Java Beans are used for creating distributed applications in java. The java programs can
be easily distributed on one or more systems that are connected to each other through an internet
connection.
6. Multithreading

Java supports multithreading, enabling the concurrent execution of multiple parts of a program. This
feature is particularly useful for applications that require high performance, such as games and real-time
simulations.
7. Portability

As we know, java code written on one machine can be run on another machine. The platform-independent
feature of java in which its platform-independent bytecode can be taken to any platform for execution
makes java portable. WORA (Write Once Run Anywhere) makes java application to generates a ‘.class’
file that corresponds to our applications(program) but contains code in binary format. It provides ease t
architecture-neutral ease as bytecode is not dependent on any machine architecture. It is the primary
reason java is used in the enterprising IT industry globally worldwide.
8. High Performance

2
Java architecture is defined in such a way that it reduces overhead during the runtime and at sometimes
java uses Just In Time (JIT) compiler where the compiler compiles code on-demand basis where it only
compiles those methods that are called making applications to execute faster.

Structured vs Object-Oriented Programming


1. Structured Programming

Structured Programming, as name suggests, is a technique that is considered as precursor to OOP and
usually consists of well-structured and separated modules. In this programming, user can create its own
user-defined functions as well as this methodology tries to resolve issues that are associated with
unconditional transfers to allow programmers follow logic of programs. It also requires more discipline
at the design and logical structuring stage.
Example : Pascal, ALGOL, C, Modula-2, etc.
2. Object-Oriented Programming
Object-Oriented Programming, as name suggests, is a different approach to programming that brings
together data and functions that execute on them. It basically supports encapsulation, abstraction,
inheritance, polymorphism, etc. It also includes data hiding feature therefore it is more secure. This model
is based on real life entities that focuses on by whom task is to be done rather than focusing on what to
do.
Example : JAVA, C#, C++, etc.
Difference between Structured Programming and Object-Oriented Programming

Structured Programming Object-Oriented Programming


It is a subset of procedural programming. It relies on concept of objects that contain data and
code.
Programs are divided into small programs or Programs are divided into objects or entities.
functions.
It is all about facilitating creation of programs It is all about creating objects that usually contain both
with readable code and reusable components. functions and data.
Its main aim is to improve and increase quality, Its main aim is to improve and increase both quality
clarity, and development time of computer and productivity of system analysis and design.
program.
It simply focuses on functions and processes It simply focuses on representing both structure and
that usually work on data. behavior of information system into tiny or small
modules that generally combines data and process
both.
It is a method of organizing, managing and It is a method in which set of objects can vary
coding programs that can give or provide much dynamically and can execute just by acting and
easier modification and understanding. reading to each other.
In this, methods are written globally and code In this, method works dynamically, make calls as per
lines are processed one by one i.e., Run need of code for certain time.
sequentially.

3
It generally follows “Top-Down Approach”. It generally follows “Bottom-Up Approach”.
It provides less flexibility and abstraction as It provides more flexibility and abstraction as
compared to object-oriented programming. compared to structured programming.
It is more difficult to modify structured program It is less difficult to modify object-oriented programs
and reuse code as compared to object-oriented and reuse code as compared to structured programs.
programs.
It gives more importance of code. It gives more importance to data.

Java Applications
Since Java supports object-oriented features and is platform-independent, it is extensively used in various
fields. Listed below are a few areas where Java is used -

• Enterprise solutions • Embedded systems


• Game development • Mobile application development
• Secured web development • Big Data Applications, and many more.

Essential Java Terminologies

Before learning Java, one must be familiar with these common terms of Java.
Java Virtual Machine (JVM)

The JVM is an integral part of the Java platform, responsible for executing Java bytecode. It ensures that
the output of Java programs is consistent across different platforms.
1. Writing a program is done by a java programmer like you and me.
2. The compilation is done by the JAVAC compiler which is a primary Java compiler
included in the Java development kit (JDK). It takes the Java program as input and generates
bytecode as output.
3. In the Running phase of a program, JVM executes the bytecode generated by the compiler.
Now, we understood that the function of Java Virtual Machine is to execute the bytecode produced by
the compiler. Every Operating System has a different JVM but the output they produce after the
execution of bytecode is the same across all the operating systems. This is why Java is known as
a platform-independent language.
Bytecode

Bytecode is the intermediate representation of Java code, generated by the Java compiler. It is platform-
independent and can be executed by the JVM.
Java Development Kit (JDK)

4
While we were using the term JDK when we learn about bytecode and JVM. So, as the name suggests, it
is a complete Java development kit that includes everything including compiler, Java Runtime
Environment (JRE), Java Debuggers, Java Docs, etc. For the program to execute in java, we need to
install JDK on our computer in order to create, compile and run the java program.
Java Runtime Environment (JRE)

JDK includes JRE. JRE installation on our computers allows the java program to run, however, we cannot
compile it. JRE includes a browser, JVM, applet support, and plugins. For running the java program, a
computer needs JRE.
Garbage Collector

In Java, programmers can’t delete the objects. To delete or recollect that memory JVM has a program
called Garbage Collector. Garbage Collectors can recollect the objects that are not referenced.
So, Java makes the life of a programmer easy by handling memory management. However, programmers
should be careful about their code whether they are using objects that have been used for a long time.
Because Garbage cannot recover the memory of objects being referenced.
ClassPath

The Classpath is the file path where the java runtime and Java compiler look for .class files to load. By
default, JDK provides many libraries. If you want to include external libraries, they should be added to
the classpath.
Basically, everything in java is represented in Class as an object including the main function.
Advantages of Java

• Platform independent: Java code can run on any platform that has a Java Virtual Machine
(JVM) installed, which means that applications can be written once and run on any device.
• Object-Oriented: Java is an object-oriented programming language, which means that it
follows the principles of encapsulation, inheritance, and polymorphism.
• Security: Java has built-in security features that make it a secure platform for developing
applications, such as automatic memory management and type checking.
• Large community: Java has a large and active community of developers, which means that
there is a lot of support available for learning and using the language.
• Enterprise-level applications: Java is widely used for developing enterprise-level
applications, such as web applications, e-commerce systems, and database systems.
Disadvantages of Java

1. Performance: Java can be slower compared to other programming languages, such as C++,
due to its use of a virtual machine and automatic memory management.

5
2. Memory management: Java’s automatic memory management can lead to slower
performance and increased memory usage, which can be a drawback for some applications.

Basic Syntax

About Java programs, it is very important to keep in mind the following points.

• Case Sensitivity − Java is case sensitive, which means identifier Hello and hello would have
different meaning in Java.
• Class Names − For all class names the first letter should be in Upper Case. If several words are
used to form a name of the class, each inner word's first letter should be in Upper Case.
Example − class MyFirstJavaClass
• Method Names − All method names should start with a Lower-Case letter. If several words are
used to form the name of the method, then each inner word's first letter should be in Upper Case.
Example − public void myMethodName()
• Program File Name − Name of the program file should exactly match the class name.
When saving the file, you should save it using the class name (Remember Java is case sensitive)
and append '.java' to the end of the name (if the file name and the class name do not match, your
program will not compile).
But please make a note that in case you do not have a public class present in the file then file name
can be different than class name. It is also not mandatory to have a public class in the file.
Example − Assume 'MyFirstJavaProgram' is the class name. Then the file should be saved
as 'MyFirstJavaProgram.java'
• public static void main(String args[]) − Java program processing starts from the main() method
which is a mandatory part of every Java program.

Java Identifiers

All Java components require names. Names used for classes, variables, and methods are called identifiers.
In Java, there are several points to remember about identifiers. They are as follows:

• All identifiers should begin with a letter (A to Z or a to z), currency character ($) or an underscore
(_).
• After the first character, identifiers can have any combination of characters.
• A keyword cannot be used as an identifier.
• Most importantly, identifiers are case sensitive.

6
• Examples of legal identifiers: age, $salary, _value, __1_value.
• Examples of illegal identifiers: 123abc, -salary.

Modifiers

Like other languages, it is possible to modify classes, methods, etc., by using modifiers. There are two
categories of modifiers:

• Access Modifiers − default, public, protected, private


• Non-access Modifiers − final, abstract, strictfp

Data Types
As the name suggests, data types specify the type of data that can be stored inside variables in Java. Java
is a statically-typed language. This means that all variables must be declared before they can be used.
int speed; Here, speed is a variable, and the data type of the variable is int. The int data type
determines that the speed variable can only contain integers.

There are 8 data types predefined in Java, known as primitive data types. In addition to primitive data
types, there are also referenced types (object type).

Primitive Data Types


1. boolean type
The boolean data type has two possible values, either true or false. Default value: false. They are usually
used for true/false conditions.
Example 1: Java boolean data type
class Main {
public static void main(String[] args) {

boolean flag = true;


System.out.println(flag); // prints true
}
}
2. byte type
The byte data type can have values from -128 to 127 (8-bit signed two's complement integer).
If it's certain that the value of a variable will be within -128 to 127, then it is used instead of int to save
memory. Default value: 0

7
Example 2: Java byte data type
class Main {
public static void main(String[] args) {

byte range;
range = 124;
System.out.println(range); // prints 124
}
}
3. short type
The short data type in Java can have values from -32768 to 32767 (16-bit signed two's complement
integer). If it's certain that the value of a variable will be within -32768 and 32767, then it is used instead
of other integer data types (int, long). Default value: 0
Example 3: Java short data type
class Main {
public static void main(String[] args) {

short temperature;
temperature = -200;
System.out.println(temperature); // prints -200
}
}
4. int type
The int data type can have values from -231 to 231-1 (32-bit signed two's complement integer).
If you are using Java 8 or later, you can use an unsigned 32-bit integer. This will have a minimum value
of 0 and a maximum value of 232-1. To learn more, visit How to use the unsigned integer in java 8?
Default value: 0
Example 4: Java int data type
class Main {
public static void main(String[] args) {

int range = -4250000;


System.out.println(range); // print -4250000
}
}
5. long type
The long data type can have values from -263 to 263-1 (64-bit signed two's complement integer).
If you are using Java 8 or later, you can use an unsigned 64-bit integer with a minimum value of 0 and a
maximum value of 264-1. Default value: 0

8
Example 5: Java long data type
class LongExample {
public static void main(String[] args) {

long range = -42332200000L;


System.out.println(range); // prints -42332200000
}
}
Notice, the use of L at the end of -42332200000. This represents that it's an integer of the long type.
6. double type
The double data type is a double-precision 64-bit floating-point. It should never be used for precise values
such as currency. Default value: 0.0 (0.0d)
Example 6: Java double data type
class Main {
public static void main(String[] args) {

double number = -42.3;


System.out.println(number); // prints -42.3
}
}

7. float type
The float data type is a single-precision 32-bit floating-point. Learn more about single-precision and
double-precision floating-point if you are interested. It should never be used for precise values such as
currency. Default value: 0.0 (0.0f)
Example 7: Java float data type
class Main {
public static void main(String[] args) {

float number = -42.3f;


System.out.println(number); // prints -42.3
}
}
Notice that we have used -42.3f instead of -42.3in the above program. It's because -42.3 is a double
literal. To tell the compiler to treat -42.3 as float rather than double, you need to use f or F. If you want to
know about single-precision and double-precision, visit Java single-precision and double-precision
floating-point.

8. char type
It's a 16-bit Unicode character. The minimum value of the char data type is '\u0000' (0) and the maximum
value of the is '\uffff'. Default value: '\u0000'

9
Example 8: Java char data type
class Main {
public static void main(String[] args) {

char letter = '\u0051';


System.out.println(letter); // prints Q
}
}
Here, the Unicode value of Q is \u0051. Hence, we get Q as the output.
Here is another example:

class Main {
public static void main(String[] args) {

char letter1 = '9';


System.out.println(letter1); // prints 9

char letter2 = 65;


System.out.println(letter2); // prints A

}
}
Here, we have assigned 9 as a character (specified by single quotes) to the letter1 variable. However, the
letter2 variable is assigned 65 as an integer number (no single quotes). Hence, A is printed to the output.
It is because Java treats characters as an integer and the ASCII value of A is 65.
String type
Java also provides support for character strings via java.lang.String class. Strings in Java are not primitive
types. Instead, they are objects. For example,
String myString = "Java Programming";
Here, myString is an object of the String class. To learn more, visit Java Strings.

Java Variables
A variable provides us with named storage that our programs can manipulate. Each variable in Java has a
specific type, which determines the size and layout of the variable's memory; the range of values that can
be stored within that memory; and the set of operations that can be applied to the variable.

Variable Declaration and Initialization

You must declare all variables before they can be used. Java variables are declared by specifying the data
type followed by the variable name. To assign a value, use the assignment (=) operator followed by the
value. Each declaration or initialization statement must end with a semicolon (;).

10
Syntax

Following is the basic form of a variable declaration −

data type variable [ = value][, variable [ = value] ...] ;

Here data type is one of Java's data types and variable is the name of the variable. To declare more than one
variable of the specified type, you can use a comma-separated list.

Example of Valid Variables Declarations and Initializations

Following are valid examples of variable declaration and initialization in Java −

• int a, b, c; // Declares three ints, a, b, and c.


• int a = 10, b = 10; // Example of initialization
• byte B = 22; // initializes a byte type variable B.
• double pi = 3.14159; // declares and assigns a value of PI.
• char a = 'a'; // the char variable a iis initialized with value 'a'

Java Variables Types

The following are the three types of Java variables:

• Local variables
• Instance variables
• Class/Static variables

Java Local Variables

Local variables are declared in methods, constructors, or blocks. Local variables are created when the
method, constructor or block is entered and the variable will be destroyed once it exits the method,
constructor, or block.

• Access modifiers cannot be used for local variables.


• Local variables are visible only within the declared method, constructor, or block.
• Local variables are implemented at stack level internally.
• There is no default value for local variables, so local variables should be declared and an initial
value should be assigned before the first use.

Example 1: Variable's local scope with initialization

11
Here, age is a local variable. This is defined inside pupAge() method and its scope is limited to only this
method.

public class Test {


public void pupAge() {
int age = 0;
age = age + 7;
System.out.println("Puppy age is : " + age);
}
public static void main(String args[]) {
Test test = new Test();
test.pupAge();
}
}
Output

Puppy age is: 7

Example 2: Variable's local scope without initialization

Following example uses age without initializing it, so it would give an error at the time of compilation.

public class Test {


public void pupAge() {
int age;
age = age + 7;
System.out.println("Puppy age is : " + age);
}
public static void main(String args[]) {
Test test = new Test();
test.pupAge();
}
}

12
Output

Test.java:4: variable number might not have been initialized


age = age + 7;
^
1 error

Java Instance Variables

• Instance variables are declared in a class, but outside a method, constructor or any block. When a
space is allocated for an object in the heap, a slot for each instance variable value is created.
• Instance variables are created when an object is created with the use of the keyword 'new' and
destroyed when the object is destroyed.
• Instance variables hold values that must be referenced by more than one method, constructor or
block, or essential parts of an object's state that must be present throughout the class.
• Instance variables can be declared in class level before or after use.
• Access modifiers can be given for instance variables.
• The instance variables are visible for all methods, constructors and block in the class. Normally, it
is recommended to make these variables private (access level). However, visibility for subclasses
can be given for these variables with the use of access modifiers.
• Instance variables have default values. For numbers, the default value is 0, for Booleans it is false,
and for object references it is null. Values can be assigned during the declaration or within the
constructor.
• Instance variables can be accessed directly by calling the variable name inside the class. However,
within static methods (when instance variables are given accessibility), they should be called using
the fully qualified name. ObjectReference.VariableName.

Example of Java Instance Variables

import java.io.*;
public class Employee {
// this instance variable is visible for any child class.
public String name;
// salary variable is visible in Employee class only.

13
private double salary;
// The name variable is assigned in the constructor.
public Employee (String empName) {
name = empName;
}
// The salary variable is assigned a value.
public void setSalary(double empSal) {
salary = empSal;
}
// This method prints the employee details.
public void printEmp() {
System.out.println("name : " + name );
System.out.println("salary :" + salary);
}
public static void main(String args[]) {
Employee empOne = new Employee("Ransika");
empOne.setSalary(1000);
empOne.printEmp();
}
}
Output

name : Ransika
salary :1000.0

Java Class/Static Variables

• Class variables also known as static variables are declared with the static keyword in a class, but
outside a method, constructor or a block.
• There would only be one copy of each class variable per class, regardless of how many objects are
created from it.

14
• Static variables are rarely used other than being declared as constants. Constants are variables that
are declared as public/private, final, and static. Constant variables never change from their initial
value.
• Static variables are stored in the static memory. It is rare to use static variables other than declared
final and used as either public or private constants.
• Static variables are created when the program starts and destroyed when the program stops.
• Visibility is similar to instance variables. However, most static variables are declared public since
they must be available for users of the class.
• Default values are same as instance variables. For numbers, the default value is 0; for Booleans, it
is false; and for object references, it is null. Values can be assigned during the declaration or within
the constructor. Additionally, values can be assigned in special static initializer blocks.
• Static variables can be accessed by calling with the class name ClassName.VariableName.
• When declaring class variables as public static final, then variable names (constants) are all in upper
case. If the static variables are not public and final, the naming syntax is the same as instance and
local variables.

Example of Java Class/Static Variables

import java.io.*;
public class Employee {
// salary variable is a private static variable
private static double salary;
// DEPARTMENT is a constant
public static final String DEPARTMENT = "Development ";
public static void main(String args[]) {
salary = 1000;
System.out.println(DEPARTMENT + "average salary:" + salary);
}
}
Output

Development average salary:1000

15
Note − If the variables are accessed from an outside class, the constant should be accessed as
Employee.DEPARTMENT

Statements in Java
Statement is an executable instruction that tells the compiler what to perform. It forms a complete command
to be executed and can include one or more expressions. A sentence forms a complete idea that can include
one or more clauses.

Types of Statements

Java statements can be broadly classified into the following categories:

• Expression Statements
• Declaration Statements
• Control Statements

Figure 1: Types of Statements

Expression Statements

Expression is an essential building block of any Java program. Generally, it is used to generate a new
value. Sometimes, we can also assign a value to a variable. In Java, expression is the combination of
values, variables, operators, and method calls.

There are three types of expressions in Java:

16
• Expressions that produce a value. For example, (6+9), (9%2), (pi*radius) + 2. Note that the
expression enclosed in the parentheses will be evaluate first, after that rest of the expression.
• Expressions that assign a value. For example, number = 90, pi = 3.14.
• Expression that neither produces any result nor assigns a value. For example, increment or
decrement a value by using increment or decrement operator respectively, method invocation, etc.
These expressions modify the value of a variable or state (memory) of a program. For example,
count++, int sum = a + b; The expression changes only the value of the variable sum. The value
of variables a and b do not change, so it is also a side effect.

Declaration Statements

In declaration statements, we declare variables and constants by specifying their data type and name. A
variable holds a value that is going to use in the Java program. For example:

• int quantity;
• boolean flag;
• String message;

Also, we can initialize a value to a variable. For example:

• int quantity = 20;


• boolean flag = false;
• String message = "Hello";

Java also allows us to declare multiple variables in a single declaration statement. Note that all the
variables must be of the same data type.

• int quantity, batch_number, lot_number;


• boolean flag = false, isContains = true;
• String message = "Hello", how are you;

Control Statement

Control statements decide the flow (order or sequence of execution of statements) of a Java program. In
Java, statements are parsed from top to bottom. Therefore, using the control flow statements can interrupt
a particular section of a program based on a certain condition.

17
Figure 2: Types of Statements in Java

Conditional or Selection Statements

1. Java if (if-then) Statement

syntax:
if (condition) {
// statements
}
Here, condition is a boolean expression such as age >= 18.

• if condition evaluates to true, the lines of code inside if are executed


• if condition evaluates to false, the lines of code inside if are skipped

Working of if Statement

18
• if the number is greater than 0, code inside if block is executed, otherwise code inside if block is
skipped

Example: Java if Statement

class IfStatement {
public static void main(String[] args) {
int number = 10;
// checks if number is less than 0
if (number < 0) {
System.out.println("The number is negative.");
}
System.out.println("Statement outside if block");
}
}
Output

Statement outside if block

In the program, number < 0 is false. Hence, the code inside the body of the if statement is skipped.

Note: If you want to learn more about about test conditions, visit Java Relational Operators and Java
Logical Operators.

We can also use Java Strings as the test condition.

Example: Java if with String

class Main {
public static void main(String[] args) {
// create a string variable
String language = "Java";
// if statement
if (language == "Java") {
System.out.println("Best Programming Language");

19
}
}
}
Output

Best Programming Language

In the above example, we are comparing two strings in the if block.

2. Java if...else (if-then-else) Statement

The if statement executes a certain section of code if the test expression is evaluated to true. However, if
the test expression is evaluated to false, it does nothing.

In this case, we can use an optional else block. Statements inside the body of else block are executed if
the test expression is evaluated to false. This is known as the if-...else statement in Java.

The syntax of the if...else statement is:

if (condition) {
// codes in if block
}
else {
// codes in else block
}
Here, the program will do one task (codes inside if block) if the condition is true and another task (codes
inside else block) if the condition is false.

How the if...else statement works?

If the condition is true, the code inside the if block is executed, otherwise, code inside the else block is
executed.

20
Example: Java if...else Statement

class Main {
public static void main(String[] args) {
int number = 10;
// checks if number is greater than 0
if (number > 0) {
System.out.println("The number is positive.");
}
// execute this block
// if number is not greater than 0
else {
System.out.println("The number is not positive.");
}

System.out.println("Statement outside if...else block");


}
}
Output

The number is positive.


Statement outside if...else block

21
In the above example, we have a variable named number. Here, the test expression number > 0 checks if
number is greater than 0.

Since the value of the number is 10, the test expression evaluates to true. Hence code inside the body of if
is executed.

Now, change the value of the number to a negative integer. Let's say -5.

• int number = -5;

If we run the program with the new value of number, the output will be:

The number is not positive.

• Statement outside if...else block

Here, the value of number is -5. So the test expression evaluates to false. Hence code inside the body of
else is executed.

3. Java if...else...if Statement

In Java, we have an if...else...if ladder, that can be used to execute one block of code among multiple
other blocks.

if (condition1) {
// codes
}
else if(condition2) {
// codes
}
else if (condition3) {
// codes
}
.
.
else {

22
// codes
}
Here, if statements are executed from the top towards the bottom. When the test condition is true, codes
inside the body of that if block is executed. And, program control jumps outside the if...else...if ladder.

If all test expressions are false, codes inside the body of else are executed.

How the if...else...if ladder works?

If the first test condition if true, code inside first if block is executed, if the second condition is true, block
inside second if is executed, and if all conditions are false, the else block is executed

Example: Java if...else...if Statement

class Main {
public static void main(String[] args) {
int number = 0;
// checks if number is greater than 0
if (number > 0) {
System.out.println("The number is positive.");
}
// checks if number is less than 0
else if (number < 0) {
System.out.println("The number is negative.");

23
}
// if both condition is false
else {
System.out.println("The number is 0.");
}
}
}
Output

The number is 0.

In the above example, we are checking whether number is positive, negative, or zero. Here, we have two
condition expressions:

• number > 0 - checks if number is greater than 0


• number < 0 - checks if number is less than 0

Here, the value of number is 0. So both the conditions evaluate to false. Hence the statement inside the
body of else is executed.

Note: Java provides a special operator called ternary operator, which is a kind of shorthand notation of
if...else...if statement. To learn about the ternary operator, visit Java Ternary Operator.

4. Java Nested if..else Statement

In Java, it is also possible to use if..else statements inside an if...else statement. It's called the nested
if...else statement.

Here's a program to find the largest of 3 numbers using the nested if...else statement.

Example: Nested if...else Statement

class Main {
public static void main(String[] args) {
// declaring double type variables
Double n1 = -1.0, n2 = 4.5, n3 = -5.3, largest;
// checks if n1 is greater than or equal to n2

24
if (n1 >= n2) {
// if...else statement inside the if block
// checks if n1 is greater than or equal to n3
if (n1 >= n3) {
largest = n1;
}
else {
largest = n3;
}
} else {
// if..else statement inside else block
// checks if n2 is greater than or equal to n3
if (n2 >= n3) {
largest = n2;
}
else {
largest = n3;
}
}
System.out.println("Largest Number: " + largest);
}
}
Output:

Largest Number: 4.5

In the above programs, we have assigned the value of variables ourselves to make this easier.

However, in real-world applications, these values may come from user input data, log files, form
submission, etc.

25
Loop or Iterative Statements

1. Java for Loop

For loops in Java are a fundamental control structure used to repeat a block of code a specific number of
times or iterate through a sequence of values. They are incredibly useful for tasks that require repetition,
such as processing items in an array, generating repetitive output, or executing a block of code a
predetermined number of times.

The Java for loop is used to iterate a part of the program several times. If the number of iteration is fixed,
it is recommended to use for loop.

There are the following three types of for loops in Java.

• Simple for Loop


• For-each or Enhanced for Loop
• Labelled for Loop

Java Simple for Loop

A simple for loop is the same as C/C++. We can initialize the variable, check condition and
increment/decrement value. It consists of four parts:

• Initialization: It is the initial condition which is executed once when the loop starts. Here, we can
initialize the variable, or we can use an already initialized variable. It is an optional condition.
• Condition: It is the second condition which is executed each time to test the condition of the
loop. It continues execution until the condition is false. It must return boolean value either true or
false. It is an optional condition.
• Increment/Decrement: It increments or decrements the variable value. It is an optional
condition.
• Statement: The statement of the loop is executed each time until the second condition is false.

Syntax:
for (initialization; condition; increment/decrement) {
//statement or code to be executed
}
Example:

//Java Program to demonstrate the example of for loop

26
//which prints table of 1

public class ForExample {

public static void main(String[] args) {

//Code of Java for loop

for(int i=1;i<=10;i++){

System.out.println(i);

Output:

1 6
2 7
3 8
4 9
5 10

Java for-each Loop


The for-each loop is used to traverse array or collection in Java. It is easier to use than simple for loop
because we don't need to increment value and use subscript notation.
It works on the basis of elements and not the index. It returns element one by one in the defined variable.
Syntax:
for(data_type variable : array_name){
//code to be executed
}
Example:
//Java For-each loop example which prints the
//elements of the array

27
public class ForEachExample {
public static void main(String[] args) {
//Declaring an array
int arr[]={12,23,44,56,78};
//Printing array using for-each loop
for(int i:arr){
System.out.println(i);
}
}
}
Output:

12
23
44
56
78

Java Labelled for Loop


A labelled for loop in Java is a for loop that has been assigned a label. Labels in Java provide a way to
identify a block of code, making it possible to break out of or continue an outer loop from within a nested
loop. This feature is particularly useful when working with nested loops and we need to control the flow of
the outer loop from within an inner loop. Labels enhance the control flow in complex looping structures,
allowing for more precise and flexible loop management.

We can have a name of each Java for loop. To do so, we use label before the for loop. It is useful while
using the nested for loop as we can break/continue specific for loop.
Note: The break and continue keywords breaks or continues the innermost for loop respectively.
Syntax:
labelname:
for(initialization; condition; increment/decrement){
//code to be executed

28
}
Example:
//A Java program to demonstrate the use of labeled for loop
public class LabeledForExample {
public static void main(String[] args) {
//Using Label for outer and for loop
aa:
for(int i=1;i<=3;i++){
bb:
for(int j=1;j<=3;j++){
if(i==2&&j==2){
break aa;
}
System.out.println(i+" "+j);
}
}
}
}
Output:

11
12
13
21

If you use break bb;, it will break inner loop only which is the default behaviour of any loop.
public class LabeledForExample2 {
public static void main(String[] args) {
aa:
for(int i=1;i<=3;i++){
bb:

29
for(int j=1;j<=3;j++){
if(i==2&&j==2){
break bb;
}
System.out.println(i+" "+j);
}
}
}
}
Output:

11 31
12 32
13 33
21

Java Infinitive for Loop


An infinitive for loop in Java is a loop that has no termination condition, or the condition is always true,
causing the loop to run indefinitely until the program is manually terminated or interrupted by a break
statement or an exception. This type of loop is used when you want to create a continuous loop that keeps
running until an external condition or user interaction dictates otherwise.

If we use a pair of semicolons (;;) in the for loop, it will be infinitive for loop.
Syntax:
for(;;){
//code to be executed
}
Example:
//Java program to demonstrate the use of infinite for loop
//which prints an statement
public class ForExample {
public static void main(String[] args) {

30
//Using no condition in for loop
for(;;){
System.out.println("infinitive loop");
}
}
}
Output:

infinitive loop
infinitive loop
infinitive loop
infinitive loop
infinitive loop

do-while Loop

The Java do-while loop is used to iterate a part of the program repeatedly, until the specified condition is
true. If the number of iteration is not fixed and you must have to execute the loop at least once, it is
recommended to use a do-while loop.

Java do-while loop is called an exit control loop. Therefore, unlike while loop and for loop, the do-while
check the condition at the end of loop body. The Java do-while loop is executed at least once because
condition is checked after loop body.

Syntax:

do{

//code to be executed / loop body

//update statement

}while (condition);

31
Example

public class DoWhileExample {

public static void main(String[] args) {

int i=1;

do{

System.out.println(i);

i++;

}while(i<=10);

Output:

1 6
2 7
3 8
4 9
5 10

While Loop

The while loop loops through a block of code as long as a specified condition is true:

Syntax:

while (condition) {

// code block to be executed

In the example below, the code in the loop will run, over and over again, as long as a variable (i) is less
than 5:

32
Example

public class Main {


public static void main(String[] args) {
int i = 0;
while (i < 5) {
System.out.println(i);
i++;
}
}
}
Output

0
1
2
3
4

Java Arrays

Arrays are objects that store multiple variables of the same type. However, an array itself is an object on
the heap. We will look into how to declare, construct, and initialize in the upcoming chapters.

Java Enums

Enums were introduced in Java 5.0. Enums restrict a variable to have one of only a few predefined values.
The values in this enumerated list are called enums. With the use of enums it is possible to reduce the
number of bugs in your code. For example, if we consider an application for a fresh juice shop, it would
be possible to restrict the glass size to small, medium, and large. This would make sure that it would not
allow anyone to order any size other than small, medium, or large.

33
Review Questions
1. Which of the following is the correct way to start a Java program?
a) void main() c) public void main()
b) public static void main(String[] args) d) static public void main()
2. What is the default extension for Java files?
a) .java b) .class c) .jvm d) .jv
3. Which of the following is a valid Java identifier?
a) 1variable c) #variable
b) variable_1 d) variable-name

4. Which of the following is NOT a rule for Java identifiers?

a) They cannot start with a digit. c) They can include spaces.


b) They can contain underscores. d) They are case-sensitive.

5. Which of the following is a valid access modifier in Java?


a) private b) default c) internal d) package
6. Which modifier makes a method accessible to all classes in Java?
a) protected b) public c) private d) static

7. Which modifier is used to declare constants in Java?


a) final b) static c) abstract d) volatile

8. Which of the following is a primitive data type in Java?


a) String b) int c) Integer d) Array

9. What is the size of the float data type in Java?


a) 4 bytes b) 8 bytes c) 2 bytes d) 1 byte

10. Which of the following data types can store decimal values?
a) byte b) short c) float d) char

11. What is the correct way to declare a variable in Java?


a) int num = 5; c) int = 5;
b) num int = 5; d) num = int 5;

12. What will happen if a variable is declared but not initialized?


a) It will throw an error. c) It will remain undefined.
b) It will take a default value. d) It will take the value null.

13. Which of the following variable declarations is valid in Java?


a) double 5num = 0.5; c) char symbol = 'A';
b) float number = 2.3; d) String new = "hello";

34
CHAPTER TWO
BASIC OBJECT-ORIENTED CONCEPTS
As the name suggests, Object-Oriented Programming or Java OOPs concept refers to languages that
use objects in programming, they use objects as a primary source to implement what is to happen in the
code. Objects are seen by the viewer or user, performing tasks you assign.
Object-oriented programming aims to implement real-world entities
like inheritance, hiding, polymorphism, etc. in programming. The main aim of OOPs is to bind
together the data and the functions that operate on them so that no other part of the code can access this
data except that function.

Classes and Objects


A Class is a user-defined blueprint or prototype from which objects are created. It represents the set of
properties or methods that are common to all objects of one type. Using classes, you can create multiple
objects with the same behavior instead of writing their code multiple times. This includes classes for
objects occurring more than once in your code. In general, class declarations can include these
components in order:
1. Modifiers: A class can be public or have default access.
2. Class name: The class name should begin with the initial letter capitalized by convention.

35
3. Body: The class body is surrounded by braces, { }.
Properties of Java Classes

1. Class is not a real-world entity. It is just a template or blueprint or prototype from which
objects are created.
2. Class does not occupy memory.
3. Class is a group of variables of different data types and a group of methods.
4. A Class in Java can contain:
• Data member
• Method
• Constructor
• Nested Class
• Interface
Class Declaration in Java

access_modifier class <class_name>


{
data member;
method;
constructor;
nested class;
interface;
}
Example of Java Class

// Java Program for class example


class Student {
// data member (also instance variable)
int id;
// data member (also instance variable)
String name;
public static void main(String args[])
{
// creating an object of
// Student

36
Student s1 = new Student();
System.out.println(s1.id);
System.out.println(s1.name);
}
}
Output
0
null
Components of Java Classes

In general, class declarations can include these components, in order:


1. Modifiers: A class can be public or has default access.
2. Class keyword: class keyword is used to create a class.
3. Class name: The name should begin with an initial letter (capitalized by convention).
4. Superclass (if any): The name of the class’s parent (superclass), if any, preceded by the
keyword extends. A class can only extend (subclass) one parent.
5. Interfaces (if any): A comma-separated list of interfaces implemented by the class, if any,
preceded by the keyword implements. A class can implement more than one interface.
6. Body: The class body is surrounded by braces, { }.

Constructors are used for initializing new objects. Fields are variables that provide the state of the class
and its objects, and methods are used to implement the behavior of the class and its objects.
Object

An object in Java is a basic unit of Object-Oriented Programming and represents real-life entities. Objects
are the instances of a class that are created to use the attributes and methods of a class. A typical Java
program creates many objects, which as you know, interact by invoking methods. An object consists of:

• State: It is represented by attributes of an object. It also reflects the properties of an object.


• Behavior: It is represented by the methods of an object. It also reflects the response of an object
with other objects.
• Identity: It gives a unique name to an object and enables one object to interact with other
objects.

Example of an object: dog

37
Figure 3: Java Objects

Objects correspond to things found in the real world. For example, a graphics program may have

objects such as “circle”, “square”, and “menu”. An online shopping system might have objects such as

“shopping cart”, “customer”, and “product”.

Note: When we create an object which is a non-primitive data type, it’s always allocated on the heap

memory.

Declaring Objects (Also called instantiating a class)

When an object of a class is created, the class is said to be instantiated. All the instances share the

attributes and the behavior of the class. But the values of those attributes, i.e. the state are unique for

each object. A single class may have any number of instances.

Example:

Figure 4: Java Object Declaration

As we declare variables like (type name;). This notifies the compiler that we will use the name to refer

to data whose type is type. With a primitive variable, this declaration also reserves the proper amount

38
of memory for the variable. So, for reference variables, the type must be strictly a concrete class name.

In general, we can’t create objects of an abstract class or an interface.

Dog tuffy;

If we declare a reference variable(tuffy) like this, its value will be undetermined(null) until an object is

actually created and assigned to it. Simply declaring a reference variable does not create an object.

Initializing a Java object

The new operator instantiates a class by allocating memory for a new object and returning a reference

to that memory. The new operator also invokes the class constructor.

Example:

// Class Declaration

public class Dog {

// Instance Variables

String name;

String breed;

int age;

String color;

// Constructor Declaration of Class

public Dog(String name, String breed, int age,

String color)

this.name = name;

this.breed = breed;

this.age = age;

this.color = color;

// method 1

39
public String getName() { return name; }

// method 2

public String getBreed() { return breed; }

// method 3

public int getAge() { return age; }

// method 4

public String getColor() { return color; }

@Override public String toString()

return ("Hi my name is " + this.getName()

+ ".\nMy breed,age and color are "

+ this.getBreed() + "," + this.getAge()

+ "," + this.getColor());

public static void main(String[] args)

Dog tuffy

= new Dog("tuffy", "papillon", 5, "white");

System.out.println(tuffy.toString());

Output
Hi my name is tuffy.
My breed,age and color are papillon,5,white

40
Initialize by using method/function:

public class GFG {

// sw=software

static String sw_name;

static float sw_price;

static void set(String n, float p)

sw_name = n;

sw_price = p;

static void get()

System.out.println("Software name is: " + sw_name);

System.out.println("Software price is: "

+ sw_price);
}

public static void main(String args[])

GFG.set("Visual studio", 0.0f);

GFG.get();

Output
Software name is: Visual studio

Software price is: 0.0

41
This class contains a single constructor. We can recognize a constructor because its declaration uses the
same name as the class and it has no return type. The Java compiler differentiates the constructors based
on the number and the type of the arguments. The constructor in the Dog class takes four arguments. The
following statement provides “tuffy”, “papillon”,5, and “white” as values for those arguments:
Dog tuffy = new Dog("tuffy","papillon",5, "white");
The result of executing this statement can be illustrated as :

Figure 5: Memory Allocation of Java Objects

Note: All classes have at least one constructor. If a class does not explicitly declare any, the Java
compiler automatically provides a no-argument constructor, also called the default constructor. This
default constructor calls the class parent’s no-argument constructor (as it contains only one statement
i.e super();), or the Object class constructor if the class has no other parent (as the Object class is the
parent of all classes either directly or indirectly).

Ways to Create an Object of a Class

There are four ways to create objects in Java. Strictly speaking, there is only one way(by using
a new keyword), and the rest internally use a new keyword.
8. Using new keyword

It is the most common and general way to create an object in Java.


Example:
// creating object of class Test
Test t = new Test();
9. Using Class.forName(String className) method

There is a pre-defined class in java.lang package with name Class. The forName(String className)
method returns the Class object associated with the class with the given string name. We have to give a

42
fully qualified name for a class. On calling the new Instance() method on this Class object returns a
new instance of the class with the given string name.
// creating object of public class Test
// consider class Test present in com.p1 package
Test obj = (Test)Class.forName("com.p1.Test").newInstance();
10. Using clone() method

clone() method is present in the Object class. It creates and returns a copy of the object.
// creating object of class Test
Test t1 = new Test();
// creating clone of above object
Test t2 = (Test)t1.clone();
11. Deserialization

De-serialization is a technique of reading an object from the saved state in a file. Refer
to Serialization/De-Serialization in Java
FileInputStream file = new FileInputStream(filename);
ObjectInputStream in = new ObjectInputStream(file);
Object obj = in.readObject();
Creating multiple objects by one type only (A good practice)

In real-time, we need different objects of a class in different methods. Creating a number of references
for storing them is not a good practice and therefore we declare a static reference variable and use it
whenever required. In this case, the wastage of memory is less. The objects that are not referenced
anymore will be destroyed by the Garbage Collector of Java.
Example:
Test test = new Test();
test = new Test();
In the inheritance system, we use a parent class reference variable to store a sub-class object. In this
case, we can switch into different subclass objects using the same referenced variable.
Example:
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
public class Test
{

43
// using Dog object
Animal obj = new Dog();
// using Cat object
obj = new Cat();
}
Anonymous Objects in Java

Anonymous objects are objects that are instantiated but are not stored in a reference variable.
• They are used for immediate method calls.
• They will be destroyed after method calling.
• They are widely used in different libraries. For example, in AWT libraries, they are used to
perform some action on capturing an event(eg a key press).
• In the example below, when a key button(referred to by the btn) is pressed, we are simply
creating an anonymous object of EventHandler class for just calling the handle method.
btn.setOnAction(new EventHandler()
{
public void handle(ActionEvent event)
{
System.out.println("Hello World!");
}
});

Difference between Class and Objects


The differences between class and object in Java are as follows:
Class Object
Class is the blueprint of an object. It is used to An object is an instance of the class.
create objects.
No memory is allocated when a class is declared. Memory is allocated as soon as an object is
created.
A class is a group of similar objects. An object is a real-world entity such as a book,
car, etc.
Class is a logical entity. An object is a physical entity.
A class can only be declared once. Objects can be created many times as per
requirement.
An example of class can be a car. Objects of the class car can be BMW, Mercedes,
Ferrari, etc.

44
Pillars of OOP in Java
1. Abstraction

Data Abstraction is the property by virtue of which only the essential details are displayed to the user.
The trivial or non-essential units are not displayed to the user. Ex: A car is viewed as a car rather than its
individual components. Data Abstraction may also be defined as the process of identifying only the
required characteristics of an object, ignoring the irrelevant details. The properties and behaviors of an
object differentiate it from other objects of similar type and also help in classifying/grouping the object.
Consider a real-life example of a man driving a car. The man only knows that pressing the accelerators
will increase the car speed or applying brakes will stop the car, but he does not know how on pressing
the accelerator, the speed is actually increasing. He does not know about the inner mechanism of the car
or the implementation of the accelerators, brakes etc. in the car. This is what abstraction is.
Note: In Java, abstraction is achieved by interfaces and abstract classes. We can achieve 100%
abstraction using interfaces.
Below is the implementation of abstraction using Abstract class:

// abstract class

abstract class GFG {

// abstract methods declaration

abstract void add();

abstract void mul();

abstract void div();

Example

// Abstract class
abstract class Animal {
// Abstract method (does not have a body)
public abstract void animalSound();
// Regular method
public void sleep() {
System.out.println("Zzz");

45
}
}

// Subclass (inherit from Animal)


class Pig extends Animal {
public void animalSound() {
// The body of animalSound() is provided here
System.out.println("The pig says: wee wee");
}
}
class Main {
public static void main(String[] args) {
Pig myPig = new Pig(); // Create a Pig object
myPig.animalSound();
myPig.sleep();
}
}
Output

The pig says: wee wee


Zzz

2. Encapsulation

It is defined as the wrapping up of data under a single unit. It is the mechanism that binds together the
code and the data it manipulates. Another way to think about encapsulation is that it is a protective
shield that prevents the data from being accessed by the code outside this shield.
• Technically, in encapsulation, the variables or the data in a class is hidden from any other
class and can be accessed only through any member function of the class in which they are
declared.
• In encapsulation, the data in a class is hidden from other classes, which is similar to
what data-hiding does. So, the terms “encapsulation” and “data-hiding” are used
interchangeably.

46
• Encapsulation can be achieved by declaring all the variables in a class as private and
writing public methods in the class to set and get the values of the variables.
Below is the implementation of Encapsulation in Java:

1
// Encapsulation using private modifier

// Employee class contains private data

// called employee id and employee name

class Employee {

private int empid;

private String ename;

// Accessing the Element

// Using Method

public int get_id(){

return empid;

public String get_name(){

return get_name;

Encapsulation ensures that the internal workings of a class are hidden, promoting modular code. Below is
the example with Java Encapsulation:
Example
// Java Program to demonstrate
// Java Encapsulation
// Person Class
class Person {
// Encapsulating the name and age
// only approachable and used using
// methods defined
private String name;
private int age;

47
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}
// Driver Class
public class Main {
// main function
public static void main(String[] args)
{
// person object created
Person person = new Person();
person.setName("John");
person.setAge(30);

// Using methods to get the values from the


// variables
System.out.println("Name: " + person.getName());
System.out.println("Age: " + person.getAge());
}
}
Output

Name: John
Age: 30

3. Inheritance

Inheritance is an important pillar of OOP (Object Oriented Programming). It is the mechanism in Java
by which one class is allowed to inherit the features (fields and methods) of another class. We are
achieving inheritance by using extends keyword. Inheritance is also known as “is-a” relationship.
Let us discuss some frequently used important terminologies:
• Superclass: The class whose features are inherited is known as superclass (also known as
base or parent class).
• Subclass: The class that inherits the other class is known as subclass (also known as
derived or extended 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.

48
Below is the implementation of Inheritance in Java:

//base class or parent class or super class

class A{

//parent class methods

void method1(){}

void method2(){}

}
//derived class or child class or base class

class B extends A{ //Inherits parent class methods

//child class methods

void method3(){}

void method4(){}

In the example below, the Car class (subclass) inherits the attributes and methods from the Vehicle class
(superclass):
Example
class Vehicle {
protected String brand = "Ford"; // Vehicle attribute
public void honk() { // Vehicle method
System.out.println("Tuut, tuut!");
}
}

class Car extends Vehicle {


private String modelName = "Mustang"; // Car attribute
public static void main(String[] args) {

// Create a myCar object


Car myCar = new Car();

// Call the honk() method (from the Vehicle class) on the myCar object
myCar.honk();

// Display the value of the brand attribute (from the Vehicle class) and the value of the
modelName from the Car class
System.out.println(myCar.brand + " " + myCar.modelName);

49
}
}
Output

Tuut, tuut!
Ford Mustang

4. Polymorphism

It refers to the ability of object-oriented programming languages to differentiate between entities with
the same name efficiently. This is done by Java with the help of the signature and declaration of these
entities. The ability to appear in many forms is called polymorphism.
Below is the implementation of the Polymorphism:
sleep(1000) //millis

sleep(1000,2000) //millis,nanos

Types of Polymorphism

Polymorphism in Java is mainly of 2 types as mentioned below:


1. Method Overloading
2. Method Overriding
Method Overloading and Method Overriding

1. Method Overloading: Also, known as compile-time polymorphism, is the concept of Polymorphism


where more than one method shares the same name with different signature (Parameters) in a class. The
return type of these methods can or cannot be same.
2. Method Overriding: Also, known as run-time polymorphism, is the concept of Polymorphism where
method in the child class has the same name, return-type and parameters as in parent class. The child
class provides the implementation in the method already written.
Below is the implementation of both the concepts:

// Java Program to Demonstrate

// Method Overloading and Overriding

// Parent Class

class Parent {

// Method Declared

50
public void func(){

System.out.println("Parent Method func");

// Method Overloading

public void func(int a){

System.out.println("Parent Method func " + a);

// Child Class

class Child extends Parent {

// Method Overriding

@Override

public void func(int a){

System.out.println("Child Method " + a);

// Main Method

public class Main {

public static void main(String args[]){

Parent obj1 = new Parent();

obj1.func();

obj1.func(5);

Child obj2 = new Child();

obj2.func(4);

51
}

Output
Parent Method func
Parent Method func 5
Child Method 4

Review Questions
1. Which of the following best describes encapsulation in Java?
a) Grouping similar classes together
b) Hiding the implementation details of a class
c) Defining methods inside a class
d) Reusing code from other classes
2. Which of the following is NOT a pillar of object-oriented programming?
a) Inheritance c) Compilation
b) Polymorphism d) Encapsulation

3. Which of the following statements about a class in Java is correct?


a) A class is an instance of an object.
b) A class is a template for creating objects.
c) A class cannot contain methods.
d) A class must be abstract.
4. What is an object in Java?
a) A function that belongs to a class
b) A variable of type class
c) An instance of a class
d) A static method
5. Which of the following creates an object in Java?
a) new ClassName();
b) ClassName object();
c) object = ClassName();
d) new object = ClassName();
6. What is the key difference between a class and an object?
a) A class is a runtime entity, and an object is a blueprint.
b) A class is static, and objects are dynamic.
c) A class is a blueprint, and an object is an instance of the class.
d) Objects define methods, and classes only hold data.
7. Which of the following is true about objects?
a) They exist only during program execution.
b) They are independent of a class.
c) They can exist without any methods.
d) They are static entities.
8. Which of the following best describes inheritance in Java?
a) A mechanism to access private members of a class

52
b) A process where one class acquires the properties of another
c) A way to restrict access to certain methods
d) A method of overloading functions
9. What is polymorphism in Java?
a) The ability of objects to take many forms
b) Defining multiple classes with the same name
c) Allowing access to private methods
d) None of the above
10. What does abstraction in Java achieve?
a) It hides unnecessary implementation details.
b) It allows multiple inheritance.
c) It ensures faster execution of code.
d) It provides complete access to data members.

53
ADVANCED PROGRAMMING

54
Chapter One
Array in Java
An array is a collection of similar types of data. For example, if we want to store the names of 100 people
then we can create an array of the string type that can store 100 names.

String[] array = new String[100];

Here, the above array cannot store more than 100 names. The number of values in a Java array is always
fixed.

Declaring an array in Java


In Java, here is how we can declare an array.

dataType[] arrayName;

• dataType - it can be primitive data types like int, char, double, byte, etc. or Java objects

• arrayName - it is an identifier

For example,

double [] data;

Here, data is an array that can hold values of type double.

But how many elements can array this hold?

Good question! To define the number of elements that an array can hold, we have to allocate memory for
the array in Java. For example,

// declare an array
double[] data;
// allocate memory
data = new double[10];
Here, the array can store 10 elements. We can also say that the size or length of the array is 10.

55
In Java, we can declare and allocate the memory of an array in one single statement. For example,

double [] data = new double [10];

How to Initialize Arrays in Java


In Java, we can initialize arrays during declaration. For example,

//declare and initialize and array

int[] age = {12, 4, 5, 2, 5};

Here, we have created an array named age and initialized it with the values inside the curly brackets.

Note that we have not provided the size of the array. In this case, the Java compiler automatically specifies
the size by counting the number of elements in the array (i.e. 5).

In the Java array, each memory location is associated with a number. The number is known as an array
index. We can also initialize arrays in Java, using the index number. For example,

// declare an array
int[] age = new int[5];

// initialize array
age[0] = 12;
age[1] = 4;
age[2] = 5;
..

Java Arrays initialization

Note:

• Array indices always start from 0. That is, the first element of an array is at index 0.

• If the size of an array is n, then the last element of the array will be at index n-1.

Accessing Elements of an Array


We can access the element of an array using the index number. Here is the syntax for accessing elements of
an array,

56
// access array elements
array[index];
Let's see an example of accessing array elements using index numbers.
Example: Access Array Elements
class Main {
public static void main(String[] args) {
// create an array
int[] age = {12, 4, 5, 2, 5};
// access each array elements
System.out.println("Accessing Elements of Array:");
System.out.println("First Element: " + age[0]);
System.out.println("Second Element: " + age[1]);
System.out.println("Third Element: " + age[2]);
System.out.println("Fourth Element: " + age[3]);
System.out.println("Fifth Element: " + age[4]);
}
}
Output

Accessing Elements of Array:


First Element: 12
Second Element: 4
Third Element: 5
Fourth Element: 2
Fifth Element: 5

In the above example, notice that we are using the index number to access each element of the array. We
can use loops to access all the elements of the array at once.
Looping Through Array Elements
In Java, we can also loop through each element of the array. For example,

57
Example: Using For Loop
class Main {
public static void main(String[] args) {
// create an array
int[] age = {12, 4, 5};

// loop through the array


// using for loop
System.out.println("Using for Loop:");
for(int i = 0; i < age.length; i++) {
System.out.println(age[i]);
}
}
}
Output

Using for Loop:


12
4
5

In the above example, we are using the for Loop in Java to iterate through each element of the array. Notice
the expression inside the loop, age.length Here, we are using the length property of the array to get the size
of the array.
We can also use the for-each loop to iterate through the elements of an array. For example,
Example: Using the for-each Loop
class Main {
public static void main(String[] args) {

// create an array
int[] age = {12, 4, 5};

58
// loop through the array
// using for loop
System.out.println("Using for-each Loop:");
for(int a : age) {
System.out.println(a);
}
}
}
Output

Using for-each Loop:


12
4
5

Example: Compute Sum and Average of Array Elements


class Main {
public static void main(String[] args) {
int[] numbers = {2, -9, 0, 5, 12, -25, 22, 9, 8, 12};
int sum = 0;
Double average;
// access all elements using for each loop
// add each element in sum
for (int number: numbers) {
sum += number;
}
// get the total number of elements
int arrayLength = numbers.length;
// calculate the average
// convert the average from int to double

59
average = ((double)sum / (double)arrayLength);
System.out.println("Sum = " + sum);
System.out.println("Average = " + average);
}
}
Output:

Sum = 36
Average = 3.6

In the above example, we have created an array of named numbers. We have used the for...each loop to
access each element of the array. Inside the loop, we are calculating the sum of each element. Notice the
line,
int arrayLength = number.length;

Here, we are using the length attribute of the array to calculate the size of the array. We then calculate the
average using:

average = ((double)sum / (double)arrayLength);

As you can see, we are converting the int value into double. This is called type casting in Java. To learn
more about typecasting, visit Java Type Casting.

Multidimensional Arrays
Arrays we have mentioned till now are called one-dimensional arrays. However, we can declare
multidimensional arrays in Java. A multidimensional array is an array of arrays. That is, each element of a
multidimensional array is an array itself. For example,

int[][] a = new int[3][4];

Here, we have created a multidimensional array named a. It is a 2-dimensional array, that can hold a
maximum of 12 elements,

60
Figure 6:2-dimensional Array

Remember, Java uses zero-based indexing, that is, indexing of arrays in Java starts with 0 and not 1.
Let's take another example of the multidimensional array. This time we will be creating a 3-dimensional
array. For example,
String[][][] data = new String[3][4][2];

Here, data is a 3d array that can hold a maximum of 24 (3*4*2) elements of type String.
Initializing a 2d array
Here is how we can initialize a 2-dimensional array in Java.
int[][] a = {
{1, 2, 3},
{4, 5, 6, 9},
{7},
};

As we can see, each element of the multidimensional array is an array itself. And also, unlike C/C++,
each row of the multidimensional array in Java can be of different lengths.

61
Figure 7: Initialization of 2-dimensional Array

Example: 2-dimensional Array

class MultidimensionalArray {
public static void main(String[] args) {
// create a 2d array
int[][] a = {
{1, 2, 3},
{4, 5, 6, 9},
{7},
};
// calculate the length of each row
System.out.println("Length of row 1: " + a[0].length);
System.out.println("Length of row 2: " + a[1].length);
System.out.println("Length of row 3: " + a[2].length);
}
}

62
Output:

Length of row 1: 3
Length of row 2: 4
Length of row 3: 1

In the above example, we are creating a multidimensional array named a. Since each component of a
multidimensional array is also an array (a[0], a[1] and a[2] are also arrays). Here, we are using the length
attribute to calculate the length of each row.
Example: Print all elements of 2d array Using Loop
class MultidimensionalArray {
public static void main(String[] args) {

int[][] a = {
{1, -2, 3},
{-4, -5, 6, 9},
{7},
};
for (int i = 0; i < a.length; ++i) {
for(int j = 0; j < a[i].length; ++j) {
System.out.println(a[i][j]);
}
}
}
}

63
Output:

1
-2
3
-4
-5
6
9
7

We can also use the for...each loop to access elements of the multidimensional array. For example,
class MultidimensionalArray {
public static void main(String[] args) {

// create a 2d array
int[][] a = {
{1, -2, 3},
{-4, -5, 6, 9},
{7},
};

// first for...each loop access the individual array


// inside the 2d array
for (int[] innerArray: a) {
// second for...each loop access each element inside the row
for(int data: innerArray) {
System.out.println(data);
}

64
}
}
}

Output:

1
-2
3
-4
-5
6
9
7

In the above example, we are have created a 2d array named a. We then used for loop and for...each loop
to access each element of the array.
Initializing a 3d array
Let's see how we can use a 3d array in Java. We can initialize a 3d array similar to the 2d array. For
example,
// test is a 3d array
int[][][] test = {
{
{1, -2, 3},
{2, 3, 4}
},
{
{-4, -5, 6, 9},
{1},
{2, 3}
}
};

65
Basically, a 3d array is an array of 2d arrays. The rows of a 3d array can also vary in length just like in a
2d array.
Example: 3-dimensional Array
class ThreeArray {
public static void main(String[] args) {
// create a 3d array
int[][][] test = {
{
{1, -2, 3},
{2, 3, 4}
},
{
{-4, -5, 6, 9},
{1},
{2, 3}
}
};

// for..each loop to iterate through elements of 3d array


for (int[][] array2D: test) {
for (int[] array1D: array2D) {
for(int item: array1D) {
System.out.println(item);
}
}
}
}
}

Output:

66
1 -4
-2 -5
3 6
2 9
3 1
4 2
3

Review Questions
1. What is an array in Java?
a) A collection of methods
b) A collection of variables of the same type
c) A collection of classes
d) A type of object
2. Which of the following is the correct way to declare and initialize an array in Java?
a) int arr = {1, 2, 3}; c) int[] arr = new int[3]{1, 2, 3};
b) int arr[] = new int[3]; d) int arr = new int[3];
3. What is the index of the first element in an array in Java?
a) 0 c) -1
b) 1 d) Depends on the array size

4. What will happen if you try to access an array index that is out of bounds?
a) The program will crash. c) It will return a default value.
b) A runtime exception will be thrown. d) Nothing will happen.

5. How do you find the size of an array in Java?


a) array.size() c) array.length
b) array.length() d) array.getLength()

67
Chapter Two
Java Exception
An exception is an unexpected event that occurs during program execution. It affects the flow of the
program instructions which can cause the program to terminate abnormally. An exception can occur for
many reasons. Some of them are:

• Invalid user input


• Device failure
• Loss of network connection
• Physical limitations (out of disk memory)
• Code errors
• Opening an unavailable file
Java Exception hierarchy
Here is a simplified diagram of the exception hierarchy in Java.

As you can see from the image above, the Throwable class is the root class in the hierarchy.
Note that the hierarchy splits into two branches: Error and Exception.
Errors
Errors represent irrecoverable conditions such as Java virtual machine (JVM) running out of memory,
memory leaks, stack overflow errors, library incompatibility, infinite recursion, etc.
Errors are usually beyond the control of the programmer and we should not try to handle errors.

68
Exceptions
Exceptions can be caught and handled by the program.
When an exception occurs within a method, it creates an object. This object is called the exception object.
It contains information about the exception such as the name and description of the exception and state of
the program when the exception occurred.
We will learn how to handle these exceptions in the next tutorial. In this tutorial, we will now focus on
different types of exceptions in Java.
Java Exception Types
The exception hierarchy also has two branches: RuntimeException and IOException.

11. RuntimeException
A runtime exception happens due to a programming error. They are also known as unchecked exceptions.
These exceptions are not checked at compile-time but run-time. Some of the common runtime exceptions
are:

• Improper use of an API - IllegalArgumentException


• Null pointer access (missing the initialization of a variable) - NullPointerException
• Out-of-bounds array access - ArrayIndexOutOfBoundsException
• Dividing a number by 0 - ArithmeticException
You can think about it in this way. "If it is a runtime exception, it is your fault".
The NullPointerException would not have occurred if you had checked whether the variable was
initialized or not before using it.
An ArrayIndexOutOfBoundsException would not have occurred if you tested the array index against
the array bounds.
12. IOException
An IOException is also known as a checked exception. They are checked by the compiler at the compile-
time and the programmer is prompted to handle these exceptions.
Some of the examples of checked exceptions are:

• Trying to open a file that doesn't exist results in FileNotFoundException


• Trying to read past the end of a file
Now we know about exceptions, we will learn about handling exceptions in the next tutorial.
Java Exception Handling
In the last tutorial, we learned about Java exceptions. We know that exceptions abnormally terminate the
execution of a program.

69
This is why it is important to handle exceptions. Here's a list of different approaches to handle exceptions
in Java.

• try...catch block
• finally block
• throw and throws keyword

1. Java try...catch block


The try-catch block is used to handle exceptions in Java. Here's the syntax of try...catch block:
try {
// code
}
catch(Exception e) {
// code
}

Here, we have placed the code that might generate an exception inside the try block. Every try block is
followed by a catch block. When an exception occurs, it is caught by the catch block. The catch block
cannot be used without the try block.

Example: Exception handling using try...catch


class Main {
public static void main(String[] args) {
try {
// code that generate exception
int divideByZero = 5 / 0;
System.out.println("Rest of code in try block");
}
catch (ArithmeticException e) {
System.out.println("ArithmeticException => " + e.getMessage());
}
}
}

70
Output

ArithmeticException => / by zero

In the example, we are trying to divide a number by 0. Here, this code generates an exception. To handle
the exception, we have put the code, 5 / 0 inside the try block. Now when an exception occurs, the rest of
the code inside the try block is skipped. The catch block catches the exception and statements inside the
catch block is executed. If none of the statements in the try block generates an exception, the catch block
is skipped.

2. Java finally block


In Java, the finally block is always executed no matter whether there is an exception or not. The finally
block is optional. And, for each try block, there can be only one finally block.
The basic syntax of finally block is:
try {
//code
}
catch (ExceptionType1 e1) {
// catch block
}
finally {
// finally block always executes
}
If an exception occurs, the finally block is executed after the try...catch block. Otherwise, it is executed
after the try block. For each try block, there can be only one finally block.
Example: Java Exception Handling using finally block
class Main {
public static void main(String[] args) {
try {
// code that generates exception
int divideByZero = 5 / 0;

71
}
catch (ArithmeticException e) {
System.out.println("ArithmeticException => " + e.getMessage());
}
finally {
System.out.println("This is the finally block");
}
}
}

Output

ArithmeticException => / by zero


This is the finally block

In the above example, we are dividing a number by 0 inside the try block. Here, this code generates an
ArithmeticException. The exception is caught by the catch block. And, then the finally block is executed.

Note: It is a good practice to use the finally block. It is because it can include important cleanup codes
like, code that might be accidentally skipped by return, continue or break closing a file or connection

3. Java throw and throws keyword


The Java throw keyword is used to explicitly throw a single exception.
When we throw an exception, the flow of the program moves from the try block to the catch block.
Example: Exception handling using Java throw
class Main {
public static void divideByZero() {
// throw an exception
throw new ArithmeticException("Trying to divide by 0");
}

public static void main(String[] args) {

72
divideByZero();
}
}

Output

Exception in thread "main" java.lang.ArithmeticException: Trying to divide by 0


at Main.divideByZero(Main.java:5)
at Main.main(Main.java:9)

In the above example, we are explicitly throwing the ArithmeticException using the throw keyword.
Similarly, the throws keyword is used to declare the type of exceptions that might occur within the
method. It is used in the method declaration.
Example: Java throws keyword
import java.io.*;
class Main {
// declareing the type of exception
public static void findFile() throws IOException {
// code that may generate IOException
File newFile = new File("test.txt");
FileInputStream stream = new FileInputStream(newFile);
}
public static void main(String[] args) {
try {
findFile();
}
catch (IOException e) {
System.out.println(e);
}
}
}

73
Output

java.io.FileNotFoundException: test.txt (The system cannot find the file specified)

When we run this program, if the file test.txt does not exist, FileInputStream throws a
FileNotFoundException which extends the IOException class. The findFile() method specifies that an
IOException can be thrown. The main() method calls this method and handles the exception if it is
thrown. If a method does not handle exceptions, the type of exceptions that may occur within it must be
specified in the throws clause.

Review Questions
1. What is an exception in Java?
a) A logical error in the code
b) A runtime error that disrupts the normal flow of the program
c) A compilation error
d) A warning issued by the compiler
2. Which of the following keywords is used to handle exceptions in Java?
a) catch b) throw c) throws d) try

3. Which of the following is an example of a checked exception in Java?


a) ArithmeticException c) IOException
b) ArrayIndexOutOfBoundsException d) NullPointerException

4. How can you create a custom exception in Java?


a) By using the Exception class directly
b) By extending the Throwable class
c) By creating a class that extends the Exception class
d) By overriding the RuntimeException class
5. What is the purpose of the finally block in exception handling?
a) To execute code only when an exception occurs
b) To handle specific types of exceptions
c) To execute code regardless of whether an exception occurs or not
d) To re-throw an exception

74
Chapter Three
Multithreading in java
A thread in Java is the smallest unit of execution that allows a program to perform multiple tasks
concurrently. Java provides a robust multithreading mechanism to achieve parallel execution of code.

Multithreading is a Java feature that allows concurrent execution of two or more parts of a program for
maximum utilization of CPU. Each part of such program is called a thread. So, threads are light-weight
processes within a process.

Typically, we can define threads as a subprocess with lightweight with the smallest unit of processes and
also has separate paths of execution. The main advantage of multiple threads is efficiency (allowing
multiple things at the same time). For example, in MS Word. one thread automatically formats the document
while another thread is taking user input. Another advantage is quick response, if we use multiple threads
in a process and if a thread gets stuck due to lack of resources or an exception, the other threads can continue
to execution, allowing the process (which represents an application) to continue to be responsive.

Figure 8: Threads in a Shared Memory Environment in OS

As we can observe in, the above diagram a thread runs inside the process and there will be context-based
switching between threads there can be multiple processes running in OS, and each process again can have

75
multiple threads running simultaneously. The Multithreading concept is popularly applied in games,
animation…etc.

The Concept of Multitasking


To help users Operating System accommodates users the privilege of multitasking, where users can
perform multiple actions simultaneously on the machine. This Multitasking can be enabled in two ways:

13. Process-Based Multitasking


14. Thread-Based Multitasking
1. Process-Based Multitasking (Multiprocessing)

In this type of Multitasking, processes are heavyweight and each process was allocated by a separate
memory area. And as the process is heavyweight the cost of communication between processes is high
and it takes a long time for switching between processes as it involves actions such as loading, saving in
registers, updating maps, lists, etc.

2. Thread-Based Multitasking

As we discussed above Threads are provided with lightweight nature and share the same address space,
and the cost of communication between threads is also low.

Why Threads are used?

Now, we can understand why threads are being used as they had the advantage of being lightweight and
can provide communication between multiple threads at a Low Cost contributing to effective multi-
tasking within a shared memory environment.

Life Cycle of Thread

There are different states Thread transfers into during its lifetime, let us know about those states in the
following lines: in its lifetime, a thread undergoes the following states, namely:

1. New State
2. Active State
3. Waiting/Blocked State
4. Timed Waiting State
5. Terminated State

76
Figure 9: Life Cycle of Thread

We can see the working of different states in a Thread in the above Diagram, let us know in detail each
and every state:

1. New State

By default, a Thread will be in a new state, in this state, code has not yet been run and the execution
process is not yet initiated.

2. Active State

A Thread that is a new state by default gets transferred to Active state when it invokes the start() method,
his Active state contains two sub-states namely:

• Runnable State: In This State, The Thread is ready to run at any given time and it’s the job of the
Thread Scheduler to provide the thread time for the runnable state preserved threads. A program
that has obtained Multithreading shares slices of time intervals which are shared between threads
hence, these threads run for some short span of time and wait in the runnable state to get their
schedules slice of a time interval.

77
• Running State: When The Thread Receives CPU allocated by Thread Scheduler, it transfers
from the “Runnable” state to the “Running” state. and after the expiry of its given time slice
session, it again moves back to the “Runnable” state and waits for its next time slice.
3. Waiting/Blocked State

If a Thread is inactive but on a temporary time, then either it is a waiting or blocked state, for example, if
there are two threads, T1 and T2 where T1 needs to communicate to the camera and the other thread T2
already using a camera to scan then T1 waits until T2 Thread completes its work, at this state T1 is parked
in waiting for the state, and in another scenario, the user called two Threads T2 and T3 with the same
functionality and both had same time slice given by Thread Scheduler then both Threads T1, T2 is in a
blocked state. When there are multiple threads parked in a Blocked/Waiting state Thread Scheduler clears
Queue by rejecting unwanted Threads and allocating CPU on a priority basis.

4. Timed Waiting State

Sometimes the longer duration of waiting for threads causes starvation, if we take an example like there are
two threads T1, T2 waiting for CPU and T1 is undergoing a Critical Coding operation and if it does not
exist the CPU until its operation gets executed then T2 will be exposed to longer waiting with undetermined
certainty, In order to avoid this starvation situation, we had Timed Waiting for the state to avoid that kind
of scenario as in Timed Waiting, each thread has a time period for which sleep() method is invoked and
after the time expires the Threads starts executing its task.

5. Terminated State

A thread will be in Terminated State, due to the below reasons:

• Termination is achieved by a Thread when it finishes its task Normally.


• Sometimes Threads may be terminated due to unusual events like segmentation faults,
exceptions…etc. and such kind of Termination can be called Abnormal Termination.
• A terminated Thread means it is dead and no longer available.

What is Main Thread?

As we are familiar, we create Main Method in each and every Java Program, which acts as an entry point
for the code to get executed by JVM, similarly in this Multithreading Concept, Each Program has one
Main Thread which was provided by default by JVM, hence whenever a program is being created in java,
JVM provides the Main Thread for its Execution.

How to Create Threads using Java Programming Language?

78
We can create Threads in java using two ways, namely:

• Extending Thread Class


• Implementing a Runnable interface
1. By Extending Thread Class

We can run Threads in Java by using Thread Class, which provides constructors and methods for creating
and performing operations on a Thread, which extends a Thread class that can implement Runnable
Interface. We use the following constructors for creating the Thread:

• Thread
• Thread(Runnable r)
• Thread(String name)
• Thread(Runnable r, String name)

Sample code to create Threads by Extending Thread Class:

import java.io.*;

import java.util.*;

public class GFG extends Thread {

// initiated run method for Thread

public void run()

System.out.println("Thread Started Running...");

public static void main(String[] args)

GFG g1 = new GFG();

// Invoking Thread using start() method

g1.start();

79
}

Output

Thread Started Running...

Sample code to create Thread by using Runnable Interface:

import java.io.*;

import java.util.*;

public class GFG implements Runnable {

// method to start Thread

public void run()

System.out.println(

"Thread is Running Successfully");

public static void main(String[] args)

GFG g1 = new GFG();

// initializing Thread Object

Thread t1 = new Thread(g1);

t1.start();

80
Output

Thread is Running Successfully

Sample Code to create Thread in Java using Thread(String name):

import java.io.*;

import java.util.*;

public class GFG {

public static void main(String args[])

// Thread object created

// and initiated with data

Thread t = new Thread("Hello Geeks!");

// Thread gets started

t.start();

// getting data of

// Thread through String

String s = t.getName();

System.out.println(s);

Output

81
Hello Geeks!

Sample Java Code which creates Thread Object by using Thread (Runnable r, String name):

import java.io.*;

import java.util.*;

public class GFG implements Runnable {

public void run()

System.out.println(

"Thread is created and running successfully...");

public static void main(String[] args)

// aligning GFG Class with

// Runnable interface

Runnable r1 = new GFG();

Thread t1 = new Thread(r1, "My Thread");

// Thread object started

t1.start();

// getting the Thread

// with String Method

String str = t1.getName();

System.out.println(str);

82
}

Output

My Thread

Thread is created and running successfully...

Java Program to explore different Thread States

Let us see the working of thread states by implementing them on Threads t1 and t2.

import java.io.*;

import java.util.*;

class GFG implements Runnable {

public void run()

// implementing try-catch Block to set sleep state

// for inactive thread

try {

Thread.sleep(102);

catch (InterruptedException i1) {

i1.printStackTrace();

System.out.println(

"The state for t1 after it invoked join method() on thread t2"

83
+ " " + ThreadState.t1.getState());

// implementing try-catch block

try {

Thread.sleep(202);

catch (InterruptedException i2) {

i2.printStackTrace();

// creation of ThreadState class

// to implement Runnable interface

public class ThreadState implements Runnable {

public static Thread t1;

public static ThreadState o1;

public static void main(String args[])

o1 = new ThreadState();

t1 = new Thread(o1);

System.out.println("post-spanning, state of t1 is"

+ " " + t1.getState());

// lets invoke start() method on t1

// Now,Thread t1 is moved to runnable state

System.out.println(

84
"post invoking of start() method, state of t1 is"

+ " " + t1.getState());

public void run()

GFG g1 = new GFG();

Thread t2 = new Thread(g1);

// Thread is created and its in new state.

t2.start();

// Now t2 is moved to runnable state

System.out.println(

"state of t2 Thread, post-calling of start() method is"

+ " " + t2.getState());

// create a try-catch block to set t1 in waiting

// state

try {

Thread.sleep(202);

catch (InterruptedException i2) {

i2.printStackTrace();

System.out.println(

"State of Thread t2 after invoking to method sleep() is"

+ " " + t2.getState());

85
try {

t2.join();

System.out.println(

"State of Thread t2 after join() is"

+ " " + t2.getState());

catch (InterruptedException i3) {

i3.printStackTrace();

System.out.println(

"state of Thread t1 after completing the execution is"

+ " " + t1.getState());

Output

post-spanning, state of t1 is NEW

post invoking of start() method, state of t1 is RUNNABLE

state of t2 Thread, post-calling of start() method is RUNNABLE

The state for t1 after it invoked join method() on thread t2 TIMED_WAITING

State of Thread t2 after invoking to method sleep() is TIMED_WAITING

State of Thread t2 after join() is TERMINATED

state of Thread t1 after completing the execution is RUNNABLE

86
Thread Priority in Multithreading
As we already know java being completely object-oriented works within a multithreading environment in
which thread scheduler assigns the processor to a thread based on the priority of thread. Whenever we create
a thread in Java, it always has some priority assigned to it. Priority can either be given by JVM while
creating the thread or it can be given by the programmer explicitly.

Priorities in threads is a concept where each thread is having a priority which in layman’s language one can
say every object is having priority here which is represented by numbers ranging from 1 to 10.

• The default priority is set to 5 as excepted.


• Minimum priority is set to 1.
• Maximum priority is set to 10.

Here 3 constants are defined in it namely as follows:

• public static int NORM_PRIORITY


• public static int MIN_PRIORITY
• public static int MAX_PRIORITY

Let us discuss it with an example to get how internally the work is getting executed. Here we will be
using the knowledge gathered above as follows:

• We will use currentThread() method to get the name of the current thread. User can also use
setName() method if he/she wants to make names of thread as per choice for understanding
purposes.
• getName() method will be used to get the name of the thread.

The accepted value of priority for a thread is in the range of 1 to 10. Let us do discuss how to get and set
priority of a thread in java.

1. public final int getPriority(): java.lang.Thread.getPriority() method returns priority of given


thread.
2. public final void setPriority(int newPriority): java.lang.Thread.setPriority() method changes
the priority of thread to the value newPriority. This method throws IllegalArgumentException if
value of parameter newPriority goes beyond minimum(1) and maximum(10) limit.

Example

87
// Java Program to Illustrate Priorities in Multithreading

// via help of getPriority() and setPriority() method

// Importing required classes

import java.lang.*;

// Main class

class ThreadDemo extends Thread {

// Method 1

// run() method for the thread that is called

// as soon as start() is invoked for thread in main()

public void run()

// Print statement

System.out.println("Inside run method");

// Main driver method

public static void main(String[] args)

// Creating random threads

// with the help of above class

ThreadDemo t1 = new ThreadDemo();

ThreadDemo t2 = new ThreadDemo();

ThreadDemo t3 = new ThreadDemo();

// Thread 1

88
// Display the priority of above thread

// using getPriority() method

System.out.println("t1 thread priority : "+ t1.getPriority());

// Thread 1

// Display the priority of above thread

System.out.println("t2 thread priority : "+ t2.getPriority());

// Thread 3

System.out.println("t3 thread priority : "+ t3.getPriority());

// Setting priorities of above threads by

// passing integer arguments

t1.setPriority(2);

t2.setPriority(5);

t3.setPriority(8);

// t3.setPriority(21); will throw

// IllegalArgumentException

// 2

System.out.println("t1 thread priority : "+ t1.getPriority());

// 5

System.out.println("t2 thread priority : "+ t2.getPriority());

// 8

System.out.println("t3 thread priority : "+ t3.getPriority());

// Main thread

// Displays the name of

// currently executing Thread

89
System.out.println(

"Currently Executing Thread : "

+ Thread.currentThread().getName());

System.out.println("Main thread priority : "+ Thread.currentThread().getPriority());

// Main thread priority is set to 10

Thread.currentThread().setPriority(10);

System.out.println("Main thread priority : "+ Thread.currentThread().getPriority());

Output

t1 thread priority : 5

t2 thread priority : 5

t3 thread priority : 5

t1 thread priority : 2

t2 thread priority : 5

t3 thread priority : 8

Currently Executing Thread : main

Main thread priority : 5

Main thread priority : 10

Output explanation:

90
Thread with the highest priority will get an execution chance prior to other threads. Suppose there are 3
threads t1, t2, and t3 with priorities 4, 6, and 1. So, thread t2 will execute first based on maximum priority
6 after that t1 will execute and then t3.

The default priority for the main thread is always 5, it can be changed later. The default priority for all other
threads depends on the priority of the parent thread.

Now geeks you must be wondering out what if we do assign the same priorities to threads then what will
happen. All the processing in order to look after threads is carried with help of the thread scheduler. One
can refer to the below example of what will happen if the priorities are set to the same and later onwards
we will discuss it as an output explanation to have a better understanding conceptually and practically.

Example

// Java program to demonstrate that a Child thread

// Getting Same Priority as Parent thread

// Importing all classes from java.lang package

import java.lang.*;

// Main class

// ThreadDemo

// Extending Thread class

class GFG extends Thread {

// Method 1

// run() method for the thread that is

// invoked as threads are started

public void run()

// Print statement

System.out.println("Inside run method");

91
// Method 2

// Main driver method

public static void main(String[] args)

// main thread priority is set to 6 now

Thread.currentThread().setPriority(6);

// Current thread is accessed

// using currentThread() method

// Print and display main thread priority

// using getPriority() method of Thread class

System.out.println("main thread priority : "+ Thread.currentThread().getPriority());

// Creating a thread by creating object inside

// main()

GFG t1 = new GFG();

// t1 thread is child of main thread

// so t1 thread will also have priority 6

// Print and display priority of current thread

System.out.println("t1 thread priority : "+ t1.getPriority());

Output

main thread priority : 6

t1 thread priority : 6

92
Output explanation:

If two threads have the same priority then we can’t expect which thread will execute first. It depends on the
thread scheduler’s algorithm (Round-Robin, First Come First Serve, etc)

If we are using thread priority for thread scheduling then we should always keep in mind that the underlying
platform should provide support for scheduling based on thread priority.

Naming a Thread
Thread can be referred to as a lightweight process. Thread uses fewer resources to create and exist in the
process; thread shares process resources. The main thread of Java is the thread that is started when the
program starts. now let us discuss the eccentric concept of with what ways we can name a thread.

Methods: There are two ways by which we can set the name either be it directly or indirectly which we
will be peeking through.

Creating the thread and Passing the thread’s name (Direct method)

Using setName() method of Thread class (Indirect Method)

Method 1: Creating the thread and passing the thread’s name

It is a direct method of naming threads in java, each thread has a name that is: Thread-0, Thread-1, Thread-
2,…. so on. Java provides some methods to change the thread name. There are basically two methods to set
the thread name. Both methods are defined in java.lang.Thread class. now you must be wondering how to
set the thread’s name directly? In java we can set the thread name at the time of creating the thread and
bypassing the thread’s name as an argument as shown in the below example as follows:

Example:

// Java Program Illustrating How to Set the name

// of Thread at time of Creation

// Importing I/O classes from java.io package

import java.io.*;

// Class 1

// Helper class

93
class ThreadNaming extends Thread {

// Parameterized constructor

ThreadNaming(String name)

// Call to constructor of

// the Thread class as super keyword

// refers to parent class

super(name);

// run() method for thread

@Override public void run()

// Print statement when thread is called inside

// main()

System.out.println("Thread is running.....");

// Class 2

// Main class

class GFG {

// main driver method

public static void main(String[] args)

94
// Creating two threads

ThreadNaming t1 = new ThreadNaming("geek1");

ThreadNaming t2 = new ThreadNaming("geek2");

// Getting the above created threads names.

System.out.println("Thread 1: " + t1.getName());

System.out.println("Thread 2: " + t2.getName());

// Starting threads using start() method

t1.start();

t2.start();

Output

Thread 1: geek1

Thread 2: geek2

Thread is running.....

Thread is running.....

Way 2: Using setName() method of Thread class

We can set(change) the thread’s name by calling the setName method on that thread object. It will change
the name of a thread.

Syntax:

public final void setName(String name)

Parameter: A string that specifies the thread name

95
Example:

// Java Program Illustrating How to Get and Change the

// Name of a Thread

// Importing input output classes

import java.io.*;

// Class 1

// Helper class extending Thread class

class ThreadNaming extends Thread {

// run() method for thread which is called

// as soon as start() is called over threads

@Override public void run()

// Print statement when run() is called over thread

System.out.println("Thread is running.....");

// Class 2

// Main class

class GFG {

// Main driver method

public static void main(String[] args)

// Creating two threads via above class

// as it is extending Thread class

96
ThreadNaming t1 = new ThreadNaming();

ThreadNaming t2 = new ThreadNaming();

// Fetching the above created threads names

// using getName() method

System.out.println("Thread 1: " + t1.getName());

System.out.println("Thread 2: " + t2.getName());

// Starting threads using start() method

t1.start();

t2.start();

// Now changing the name of threads

t1.setName("geeksforgeeks");

t2.setName("geeksquiz");

// Again getting the new names of threads

System.out.println("Thread names after changing the "+ "thread names");

// Printing the above names

System.out.println("New Thread 1 name: "+ t1.getName());

System.out.println("New Thread 2 name: "+ t2.getName());

Output

Thread 1: Thread-0

Thread 2: Thread-1

Thread is running.....

97
Thread names after changing the thread names

New Thread 1 name: geeksforgeeks

New Thread 2 name: geeksquiz

Thread is running.....

How to fetch the name of the current thread?

Now let us dwell on fetching the name of the current thread. We can fetch the current thread name at the
time of creating the thread and bypassing the thread’s name as an argument.

• Method: currentThread()
• It is defined in java.langThread class.
• Return Type: It returns a reference to the currently executing thread

Syntax:

public static Thread currentThread()

Example:

// Java program to Illustrate How to Get Name of

// Current Executing thread

// Using getName() Method

// Importing reqiored I/O classes

import java.io.*;

// Class 1

// Helper class extending to Thread class

class ThreadNaming extends Thread {

// run() method for this thread

@Override public void run()

98
// Display message

System.out.println(

"Fetching current thread name..");

// Getting the current thread name

// using getname() method

System.out.println(

Thread.currentThread().getName());

// Class 2

// Main class

class GFG {

// Main method driver

public static void main(String[] args)

// Creating two threads inside main() method

ThreadNaming t1 = new ThreadNaming();

ThreadNaming t2 = new ThreadNaming();

// Starting threads using start() method which

// automatically calls run() method

t1.start();

t2.start();

99
Output

Fetching current thread name..

Thread-0

Fetching current thread name..

Thread-1

Difference between Thread.start() and Thread.run() in Java

In Java’s multi-threading concept, start() and run() are the two most important methods. Below are some of
the differences between the Thread.start() and Thread.run() methods:

New Thread creation: When a program calls the start() method, a new thread is created and then the run()
method is executed. But if we directly call the run() method then no new thread will be created and run()
method will be executed as a normal method call on the current calling thread itself and no multi-threading
will take place. Let us understand it with an example:

class MyThread extends Thread {

public void run()

System.out.println("Current thread name: "

+ Thread.currentThread().getName());

System.out.println("run() method called");

class GeeksforGeeks {

public static void main(String[] args)

100
MyThread t = new MyThread();

t.start();

Output:

Current thread name: Thread-0

run() method called

As we can see in the above example, when we call the start() method of our thread class instance, a new
thread is created with default name Thread-0 and then run() method is called and everything inside it is
executed on the newly created thread. Now, let us try to call run() method directly instead of start()
method:

class MyThread extends Thread {

public void run()

System.out.println("Current thread name: "+ Thread.currentThread().getName());

System.out.println("run() method called");

class GeeksforGeeks {

public static void main(String[] args)

MyThread t = new MyThread();

t.run();

101
}

Output:

Current thread name: main

run() method called

As we can see in the above example, when we called the run() method of our MyThread class, no new
thread is created and the run() method is executed on the current thread i.e. main thread. Hence, no multi-
threading took place. The run() method is called as a normal function call.

Multiple invocation: In Java’s multi-threading concept, another most important difference between start()
and run() method is that we can’t call the start() method twice otherwise it will throw an
IllegalStateException whereas run() method can be called multiple times as it is just a normal method
calling.

Example

class MyThread extends Thread {

public void run()

System.out.println("Current thread name: "+ Thread.currentThread().getName());

System.out.println("run() method called");

class GeeksforGeeks {

public static void main(String[] args)

102
MyThread t = new MyThread();

t.start();

t.start();

Output:

Current thread name: Thread-0

run() method called

Exception in thread "main" java.lang.IllegalThreadStateException

at java.lang.Thread.start(Thread.java:708)

at GeeksforGeeks.main(File.java:11)

As we can see in the above example, calling start() method again raises
java.lang.IllegalThreadStateException. Now, let us try to call run() method twice:

class MyThread extends Thread {

public void run()

System.out.println("Current thread name: "+ Thread.currentThread().getName());

System.out.println("run() method called");

class GeeksforGeeks {

public static void main(String[] args)

103
{

MyThread t = new MyThread();

t.run();

t.run();

Output:

Current thread name: main

run() method called

Current thread name: main

run() method called

As we can see in the above example, calling run() method twice doesn’t raise any exception and it is
executed twice as expected but on the main thread itself.

start() run()
Creates a new thread and the run() method is No new thread is created and the run() method
executed on the newly created thread. is executed on the calling thread itself.
Can’t be invoked more than one time otherwise Multiple invocation is possible
throws java.lang.IllegalStateException
Defined in java.lang.Thread class. Defined in java.lang.Runnable interface and
must be overridden in the implementing class.

Sleeping Thread
Thread Class is a class that is basically a thread of execution of the programs. It is present in Java.lang
package. Thread class contains the Sleep() method. There are two overloaded methods of Sleep() method

104
present in Thread Class, one is with one argument and another one is with two arguments. The sleep()
method is used to stop the execution of the current thread(whichever might be executing in the system) for
a specific duration of the time and after that time duration gets over, the thread which is executing earlier
starts to execute again.

Important Point Regarding Thread.sleep() Method:

Method Whenever Thread.sleep() functions to execute, it always pauses the current thread execution.

If any other thread interrupts when the thread is sleeping, then InterruptedException will be thrown.

If the system is busy, then the actual time the thread will sleep will be more as compared to that passed
while calling the sleep method and if the system has less load, then the actual sleep time of the thread will
be close to that passed while calling sleep() method.

Syntax of Sleep() Method

There are 4 variations of the sleep() method in Java Thread. These are:

1. public static void sleep(long millis)throws InterruptedException


2. public static void sleep(long millis)throws IllegalArguementException
3. public static void sleep(long millis, int nanos)throws InterruptedException
4. public static void sleep(long millis, int nanos)throws IllegalArguementException

Parameters Passed In Thread.Sleep() Method

• millis: Duration of time in milliseconds for which thread will sleep


• nanos: This is the additional time in nanoseconds for which we want the thread to sleep. It ranges
from 0 to 999999.

Return Type of Sleep() Method: It does not return any value, i.e., the return type of the sleep function is
void.

The sleep method with one parameter is a native method, ie the implementation of this method is done in
another programming language and the other method with two parameters is not a native method, ie its
implementation is done in Java. Both the sleep methods are static, ie we can access them using the Thread
class. Both the methods throw a checked Exception ie we can handle the exception either by using the
throws keyword or by using try and catch block.

We can use Thread.Sleep() method for any thread, i.e., we can do it with the main thread or any other
thread that we make programmatically.

105
1. Using Thread.Sleep() Method For Main Thread

// Java Program for sleeping the main thread.

import java.io.*;

import java.lang.Thread;

class GFG {

public static void main(String[] args)

// we can also use throws keyword followed by

// exception name for throwing the exception

try {

for (int i = 0; i < 5; i++) {

// it will sleep the main thread for 1 sec

// ,each time the for loop runs

Thread.sleep(1000);

// printing the value of the variable

System.out.println(i);

catch (Exception e) {

// catching the exception

System.out.println(e);

106
}

Output

2. Using Thread.Sleep() Method For Custom Thread

// Java Program for sleeping the custom thread.

import java.io.*;

import java.lang.Thread;

class GFG extends Thread {

public void run()

// thread 0

// we can also use throws keyword followed by

// exception name for throwing the exception

try {

for (int i = 0; i < 5; i++) {

// it will sleep the main thread for 1 sec

// ,each time the for loop runs

Thread.sleep(1000);

107
// This Thread.sleep() method will sleep the

// thread 0.

// printing the value of the variable

System.out.println(i);

catch (Exception e) {

// catching the exception

System.out.println(e);

public static void main(String[] args)

// main thread

GFG obj = new GFG();

obj.start();

Output

108
4

3. IllegalArguementException When Sleep Time Is Negative

// Java Program for showing how exception can occur if we

// pass the negative timeout value.

import java.io.*;

import java.lang.Thread;

class GFG {

public static void main(String[] args)

// we can also use throws keyword followed by

// exception name for throwing the exception

try {

for (int i = 0; i < 5; i++) {

// this will throw the

// IllegalArgumentException

Thread.sleep(-100);

// printing the value of the variable

System.out.println(i);

catch (Exception e) {

// catching the exception

System.out.println(e);

109
}

Output

java.lang.IllegalArgumentException: timeout value is negative

Thread Synchronization
Multi-threaded programs may often come to a situation where multiple threads try to access the same
resources and finally produce erroneous and unforeseen results.

Why use Java Synchronization?

Java Synchronization is used to make sure by some synchronization method that only one thread can access
the resource at a given point in time.

Java Synchronized Blocks

Java provides a way of creating threads and synchronizing their tasks using synchronized blocks.

A synchronized block in Java is synchronized on some object. All synchronized blocks synchronize on the
same object and can only have one thread executed inside them at a time. All other threads attempting to
enter the synchronized block are blocked until the thread inside the synchronized block exits the block. If
you want to master concurrency and understand how to avoid common pitfalls, the Java Programming
Course offers in-depth coverage of synchronization with practical coding exercises.

Note: Synchronized blocks in Java are marked with the synchronized keyword.

General Form of Synchronized Block


// Only one thread can execute at a time.
// sync_object is a reference to an object
// whose lock associates with the monitor.
// The code is said to be synchronized on

110
// the monitor object
synchronized(sync_object)
{
// Access shared variables and other
// shared resources
}
This synchronization is implemented in Java with a concept called monitors or locks. 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.

Types of Synchronization
There are two synchronizations in Java mentioned below:

• Process Synchronization
• Thread Synchronization
1. Process Synchronization in Java

Process Synchronization is a technique used to coordinate the execution of multiple processes. It ensures
that the shared resources are safe and in order.

2. Thread Synchronization in Java

Thread Synchronization is used to coordinate and ordering of the execution of the threads in a multi-
threaded program. There are two types of thread synchronization are mentioned below:

• Mutual Exclusive
• Cooperation (Inter-thread communication in Java)
Mutual Exclusive
Mutual Exclusive helps keep threads from interfering with one another while sharing data. There are three
types of Mutual Exclusive mentioned below:

• Synchronized method.
• Synchronized block.
• Static synchronization.

111
Example of Synchronization

Below is the implementation of the Java Synchronization:

// A Java program to demonstrate working of


// synchronized.
import java.io.*;
import java.util.*;
// A Class used to send a message
class Sender {
public void send(String msg)
{
System.out.println("Sending\t" + msg);
try {
Thread.sleep(1000);
}
catch (Exception e) {
System.out.println("Thread interrupted.");
}
System.out.println("\n" + msg + "Sent");
}
}
// Class for send a message using Threads
class ThreadedSend extends Thread {
private String msg;
Sender sender;
// Receives a message object and a string
// message to be sent
ThreadedSend(String m, Sender obj)
{
msg = m;

112
sender = obj;
}
public void run()
{
// Only one thread can send a message
// at a time.
synchronized (sender)
{
// synchronizing the send object
sender.send(msg);
}
}
}
// Driver class
class SyncDemo {
public static void main(String args[])
{
Sender send = new Sender();
ThreadedSend S1 = new ThreadedSend(" Hi ", send);
ThreadedSend S2 = new ThreadedSend(" Bye ", send);
// Start two threads of ThreadedSend type
S1.start();
S2.start();
// wait for threads to end
try {
S1.join();
S2.join();
}
catch (Exception e) {
System.out.println("Interrupted");

113
}
}
}
Output

Sending Hi
Hi Sent
Sending Bye
Bye Sent

The output is the same every time we run the program.


Explanation
In the above example, we choose to synchronize the Sender object inside the run() method of the
ThreadedSend class. Alternately, we could define the whole send() block as synchronized, producing the
same result. Then we don’t have to synchronize the Message object inside the run() method in
ThreadedSend class.

// An alternate implementation to demonstrate


// that we can use synchronized with method also.
class Sender {
public synchronized void send(String msg)
{
System.out.println("Sending\t" + msg);
try {
Thread.sleep(1000);
}
catch (Exception e) {
System.out.println("Thread interrupted.");
}
System.out.println("\n" + msg + "Sent");
}

114
}
We do not always have to synchronize a whole method. Sometimes it is preferable to synchronize only part
of a method. Java synchronized blocks inside methods make this possible.
// One more alternate implementation to demonstrate
// that synchronized can be used with only a part of
// method
class Sender
{
public void send(String msg)
{
synchronized(this)
{
System.out.println("Sending\t" + msg );
try
{
Thread.sleep(1000);
}
catch (Exception e)
{
System.out.println("Thread interrupted.");
}
System.out.println("\n" + msg + "Sent");
}
}
}
Example of the synchronized method by using an anonymous class
// Java Pogram to synchronized method by
// using an anonymous class
import java.io.*;
class Test {

115
synchronized void test_function(int n)
{
// synchronized method
for (int i = 1; i <= 3; i++) {
System.out.println(n + i);
try {
Thread.sleep(500);
}
catch (Exception e) {
System.out.println(e);
}
}
}
}
// Driver Class
public class GFG {
// Main function
public static void main(String args[])
{
// only one object
final Test obj = new Test();
Thread a = new Thread() {
public void run() { obj.test_function(15); }
};
Thread b = new Thread() {
public void run() { obj.test_function(30); }
};
a.start();
b.start();
}

116
}
Output

16
17
18
31
32
33

Daemon Thread
In Java, daemon threads are low-priority threads that run in the background to perform tasks such as
garbage collection or provide services to user threads. The life of a daemon thread depends on the mercy
of user threads, meaning that when all user threads finish their execution, the Java Virtual Machine (JVM)
automatically terminates the daemon thread.

To put it simply, daemon threads serve user threads by handling background tasks and have no role other
than supporting the main execution.

Example of Daemon Thread in Java

Some examples of daemon threads in Java include garbage collection (gc) and finalizer. These threads
work silently in the background, performing tasks that support the main execution without interfering
with the user’s operations.

Properties of Java Daemon Thread

No Preventing JVM Exit: Daemon threads cannot prevent the JVM from exiting when all user threads
finish their execution. If all user threads complete their tasks, the JVM terminates itself, regardless of
whether any daemon threads are running.

Automatic Termination: If the JVM detects a running daemon thread, it terminates the thread and
subsequently shuts it down. The JVM does not check if the daemon thread is actively running; it
terminates it regardless.

Low Priority: Daemon threads have the lowest priority among all threads in Java.

117
Default Nature of Daemon Thread

By default, the main thread is always a non-daemon thread. However, for all other threads, their daemon
nature is inherited from their parent thread. If the parent thread is a daemon, the child thread is also a
daemon, and if the parent thread is a non-daemon, the child thread is also a non-daemon.

Note: Whenever the last non-daemon thread terminates, all the daemon threads will be terminated
automatically.

Methods of Daemon Thread

1. void setDaemon(boolean status):

This method marks the current thread as a daemon thread or user thread. Setting a user thread as a
daemon can be done using the‘tU.setDaemon(true)', while setting a daemon thread as a user thread can be
done using the ‘tD.setDaemon(false)'.

Syntax:

public final void setDaemon(boolean on)

Parameters:

on: If true, marks this thread as a daemon thread.

Exceptions:

IllegalThreadStateException: if only this thread is active.

SecurityException: if the current thread cannot modify this thread.

2. boolean isDaemon():

This method is used to check that the current thread is a daemon. It returns true if the thread is Daemon.
Else, it returns false.

Syntax:

public final boolean isDaemon()

Returns:

This method returns true if this thread is a daemon thread; false otherwise

118
// Java program to demonstrate the usage of

// setDaemon() and isDaemon() method.

public class DaemonThread extends Thread

public DaemonThread(String name){

super(name);

public void run()

// Checking whether the thread is Daemon or not

if(Thread.currentThread().isDaemon())

System.out.println(getName() + " is Daemon thread");

else

System.out.println(getName() + " is User thread");

public static void main(String[] args)

DaemonThread t1 = new DaemonThread("t1");

DaemonThread t2 = new DaemonThread("t2");

119
DaemonThread t3 = new DaemonThread("t3");

// Setting user thread t1 to Daemon

t1.setDaemon(true);

// starting first 2 threads

t1.start();

t2.start();

// Setting user thread t3 to Daemon

t3.setDaemon(true);

t3.start();

Output:

t1 is Daemon thread

t3 is Daemon thread

t2 is User thread

Exceptions in a Daemon thread

If you call the setDaemon() method after starting the thread, it would throw IllegalThreadStateException.

// Java program to demonstrate the usage of

// exception in Daemon() Thread

public class DaemonThread extends Thread

public void run()

120
{

System.out.println("Thread name: " + Thread.currentThread().getName());

System.out.println("Check if its DaemonThread: "+ Thread.currentThread().isDaemon());

public static void main(String[] args)

DaemonThread t1 = new DaemonThread();

DaemonThread t2 = new DaemonThread();

t1.start();

// Exception as the thread is already started

t1.setDaemon(true);

t2.start();

Runtime exception:

Exception in thread "main" java.lang.IllegalThreadStateException

at java.lang.Thread.setDaemon(Thread.java:1352)

at DaemonThread.main(DaemonThread.java:19)

Output:

Thread name: Thread-0

Check if its DaemonThread: false

This clearly shows that we cannot call the setDaemon() method after starting the thread.

121
Review Questions
1. What is multithreading in Java?
a) Running multiple programs simultaneously
b) Running multiple threads concurrently in a single program
c) Running one program after another in sequence
d) Running programs on multiple processors
2. Which of the following is NOT a way to create a thread in Java?
a) Extending the Thread class
b) Implementing the Runnable interface
c) Using the ThreadPoolExecutor
d) Creating a main method
3. Which state does a thread enter after calling the start() method?
a) New c) Running
b) Runnable d) Terminated

4. Why is synchronization used in Java multithreading?


a) To improve thread execution speed
b) To allow threads to access shared resources concurrently
c) To prevent data inconsistency when multiple threads access shared resources
d) To execute threads in reverse order
5. Which method is used to pause the execution of the currently executing thread?
a) wait() b) notify() c) sleep() d) yield()

6. What does the setPriority() method do in Java threads?


a) Stops the thread with the lowest priority
b) Sets the execution order of threads
c) Suggests the order in which threads should be scheduled
d) Forces the thread to execute immediately

122

You might also like