Complete Oops w Java
Complete Oops w Java
BCS-403
B.Tech-2nd Year
Course Content
for
Mission of Institute
The mission of the institute is to educate young aspirants in various technical fields to fulfill global
requirement of human resources by providing sustainable quality education, training and
invigorating environment besides molding them into skilled competent and socially responsible
citizens who will lead the building of a powerful nation.
Syllabus
Packages: Defining Package, CLASSPATH Setting for Packages, Making JAR Files
for Library Packages, Import and Static Import Naming Convention For Packages
Exception Handling: The Idea behind Exception, Exceptions & Errors, Types of Exception,
Control Flow in Exceptions, JVM Reaction to Exceptions, Use of try, catch, finally, throw,
throws in Exception Handling, In-built and User Defined Exceptions, Checked and Un-
II Checked Exceptions.
08
Input /Output Basics: Byte Streams and Character Streams, Reading and Writing File in
Java.
Lesson Plan / Teaching Plan / Lecture Plan with Progress : B Tech - CSE IV Semester : 2024-25 (Lectures)
Subject Name (Code) : Object Oriented Programming with Java(BCS403) BRANCH: CSE/CS/IT/CSIT/IOT/DS/AI/AIML
Teacher Centric Approaches => TC-1 (Chalk and Talk); TC-2 (PPT); TC-3 (Video Lectures)
Learner (Student) Centric Approaches => LC-1 (Assignment); LC-2 (Mini Project); LC-3 (Quiz); LC-4 (Seminar on recent trends); LC-5 (Group Task); Any other
Topics / lectures are arranged in sequence - same - as to be taught in the class. Maintain data related to "Date" in its hard copy.
No. of
Teaching Pedagogy
S. Lecture CO
Topic Description Reference Material
No. per (No) Teacher Student
Unit Centric Centric
Java Collections Framework: Collection in Java, Collection Framework TC1, TC2 LC1 T2, T3, T4
27 1 CO4
in Java,
Hierarchy of Collection Framework, Iterator Interface, TC1, TC2 LC1 T2, T3, T4
28 2 CO4
Collection Interface, List Interface, ArrayList, LinkedList, Vector, Stack, TC1, TC2 LC1 T2, T3, T4
29 3 CO4
Queue Interface, Set Interface, HashSet, TC1, TC2 LC1 T2, T3, T4,T5
30 4 CO4
LinkedHashSet, SortedSet Interface, TreeSet, TC1, TC2 LC1 T2, T3, T4,T5
31 5 CO4
Map Interface, HashMap Class, LinkedHashMap Class, TC1, TC2 LC1 T2, T3, T4,T5
32 6 CO4
TreeMap Class, Hashtable Class,Sorting, Comparable Interface, TC1, TC2 LC1 T2, T3, T4,T5,T6
33 7 CO4
Comparator Interface, Properties Class in Java. TC1, TC2 LC1 T2, T3, T4,T5,T6
34 8 CO4
Spring Framework: Spring Core Basics-Spring Dependency Injection TC1, TC2 LC1 T2, T3, T4,T5,T6
35 1 CO5
concepts,
Spring Inversion of Control, AOP, Bean Scopes- Singleton, TC1, TC2 LC1 T2, T4, R4, R5
36 2 CO5
Prototype, Request, Session, Application, Web Socket, TC1, TC2 LC1 T2, T4, R4, R5
37 3 CO5
Auto wiring, Annotations, Life Cycle Call backs, Bean Configuration TC1, TC2 LC1 T2, T4, R4, R5
38 4 CO5
styles
Spring Boot: Spring Boot Build Systems, TC1, TC2 LC1 T2, T4, R4, R5
39 5 CO5
Spring Boot Code Structure, Spring Boot Runners, TC1, TC2 LC1 T2, T4, R4, R5
40 6 CO5
Logger, BUILDING RESTFUL WEB SERVICES, Rest Controller, TC1, TC2 LC1 T2, T4, R4, R5
41 7 CO5
Request Mapping, Request Body, Path Variable, TC1, TC2 LC1 T2, T4, R4, R5
42 8 CO5
Request Parameter, GET, POST, PUT, DELETE APIs, Build Web TC1, TC2 LC1 T2, T4, R4, R5
43 9 CO5
Applications
S. No. DESCRIPTION
T1 Herbert Schildt, "Java The complete reference", McGraw Hill Education
T4 Greg L. Turnquist “Learning Spring Boot 2.0 - Second Edition”, Packt Publication
R1 https://www.tpointtech.com/java-tutorial
R2 https://www.w3schools.com/java/default.asp
R3 https://www.geeksforgeeks.org/java/
R4 https://www.java.com/en/
R5 https://www.programiz.com/java-programming
TABLE OF CONTENTS
1
Lecture No.:1
1.1 Java Introduction
Java is one of the most popular programming languages in the world. It is used by some 9 million
developers and it runs on around 7 billion devices worldwide according to Oracle blogs.
Java is quite easy to learn and can be understood in a short span of time as it has a syntax similar
to English.
There is a large online community of Java users ranging from beginner, intermediate, and even
expert levels that are particularly helpful in case any support is required.
Java has an abundant Application Programming Interface (API) that includes many Java classes,
packages, interfaces, etc. This is useful for constructing applications without necessarily knowing
their inside implementations. Java has mainly three types of API i.e. Official Java core APIs,
Optional official Java APIs, and Unofficial APIs. These APIs overall are used for almost
everything including networking, I/O, databases, media, XML parsing, speech synthesis, etc.
Open-source libraries have resources that can be copied, studied, changed, shared, etc. There are
multiple open source libraries in Java such as JHipster, Maven, Google Guava, Apache
Commons, etc. that can be used to make Java development easier, cheaper and faster.
There are many integrated development environments (IDEs) in Java that provide various facilities
for software development to programmers. Powerful Java IDEs such as Eclipse, NetBeans,
IntelliJ IDEA, etc. play a big role in the success of Java. These IDEs provide many facilities such
as debugging, syntax highlighting, code completion, language support, automated refactoring, etc.
that make coding in Java easier and faster. Java has created a base for the Android operating system
and opted around 90% of fortune 500 companies to develop a lot of back-end applications. Also,
2
it plays a great role in Apache Hadoop data processing, Amazon Web Services, Windows Azure,
etc.
One of the reasons Java is very popular among individual programmers is that it is available under
the Oracle Binary Code License (BCL) free of charge. This means that Java is free for development
and test environments, but for commercial purposes, a little pay is required.
Java is platform-independent as the Java source code is converted to byte code by the compiler
which can then be executed on any platform using the Java Virtual Machine. Java is also known
as a WORA (write once, run anywhere) language because it is platform-independent. Also, the
development of most Java applications occurs in a Windows environment while they are run on a
UNIX platform because of the platform-independent nature of Java.
The documentation support for Java is excellent using Javadoc which is the documentation
generator for Java. It uses the Java source code to generate the API documentation in HTML
format. So, Javadoc provides a great reference while coding in Java so that understanding the code
is quite simple.
Java is very versatile as it is used for programming applications on the web, mobile, desktop, etc.
using different platforms. Also, Java has many features such as dynamic coding, multiple security
features, and platform-independent characteristics, network-centric designing, etc. that make it
quite versatile. It doesn’t matter if you are in high school or are in the first year of your college, if
you have the curiosity to learn to code, today is the day to start.
James Gosling was leading a team named as 'Green' team. Target of this team was to create a new
project which can. Initially C++ was the original choice to develop the project. James Gosling
wanted to enhance C++ to achieve the target but due to high memory usage, that idea was rejected
and team started with a new language initially named as GreenTalk. The file extension used as .gt.
Later this language was termed as Oak and finally to Java.
3
Team put multiple names like DNA, Silk, Ruby and Java. Java was finalized by the team. James
Gosling tabled Java title based on type of espresso coffee bean. Java is an island in Indonesia where
new coffee was discovered termed as Java coffee. As per James Gosling, Java was among the top
choice along with Silk. Finally Java was selected as it was quite unique.
Sun released the first public implementation as Java 1.0 in 1996. It promised Write Once, Run
Anywhere (WORA), providing no-cost run-times on popular platforms.
On 13 November, 2006, Sun released much of Java as free and open source software under the
terms of the GNU General Public License (GPL).
4
1.4 JVM
JDK=JRE+Development Tools
One can easily install more than one version of JDK on the same computer. The Java developers
can make use of it on macOS, Windows, Linux, and Solaris.
1.4.2 JVM
JVM (Java Virtual Machine) is an abstract machine (It means not real machine, however, it acts
like a machine. Not any machine but as a machine). It is called a virtual machine because it doesn't
physically exist. It is a specification that provides a runtime environment in which Java bytecode
can be executed. It can also run those programs which are written in other languages and compiled
to Java bytecode.
JVMs are available for many hardware and software platforms. JRE, and JDK are platform
dependent because the configuration of each OS is different from each other. However, Java is
platform independent. There are three notions of the JVM: specification, implementation,
and instance.
Java Run-time Environment (JRE) is the part of the Java Development Kit (JDK). It is a freely
available software distribution which has Java Class Library, specific tools, and a stand-alone
JVM. It is the most common environment available on devices to run java programs. The source
Java code gets compiled and converted to Java bytecode. If you wish to run this bytecode on any
platform, you require JRE. The JRE loads classes, verify access to memory, and retrieves the
system resources. JRE acts as a layer on the top of the operating system. It physically exists.
JRE stands for “Java Runtime Environment” and may also be written as “Java RTE.” The
Java Runtime Environment provides the minimum requirements for executing a Java application;
it consists of the Java Virtual Machine (JVM), core classes, and supporting files.
5
1.5.2 Difference between JVM, JDK, and JRE
Table 2: JDK Vs JRE Vs JVM
JVMs are not same for all hardware and software, for example for window os JVM is different
and for Linux VJM is different.
6
Lecture No: 2
1.6 Java Source File Structure, and Compilation
o Single-line Comment: It starts with a pair of forwarding slash (//). For example:
/*It is an example of
Multiline comment*/
o Documentation Comment: It starts with the delimiter (/**) and ends with */. For
example:
7
package com.javatpoint; //where com is the root directory and javatpoint is the subdirectory
8
public class Demo //class definition
{
public static void main(String args[])
{
void display()
{
System.out.println("Welcome to javatpoint");
}
//statements
}
}
To write the simple program, you need to open notepad by start menu -> All Programs -
> Accessories -> Notepad and write a simple program as we have shown below:
9
Figure 4: output
To compile and run the above program, go to your current directory first; my current directory is
c:\new. Write here:
class CommandLineExample{
public static void main(String args[]){
System.out.println("Your first argument is: "+args[0]);
}
}
compile by > javac CommandLineExample.java
10
run by > java CommandLineExample sonoo
Example 2:
class A{
public static void main(String args[]){
for(int i=0;i<args.length;i++)
System.out.println(args[i]);
}
}
compile by > javac A.java
run by > java A sonoo jaiswal 1 3 abc
Output: sonoo
jaiswal
1
3
abc
11
Lecture No. : 3
1.7 Defining a Class in Java
Java provides a reserved keyword class to define a class. The keyword must be followed by the
class name. Inside the class, we declare methods and variables.
Syntax:
Example
int x = 5;
12
public static void main(String[] args) {
System.out.println(myObj.x);
Multiple Objects
Example
int x = 5;
System.out.println(myObj1.x);
System.out.println(myObj2.x);
}
13
}
class One {
System.out.println(myObj.x);
class Second {
int x = 5;
we used the term "variable" for x in the example (as shown below). It is actually an attribute of
the class.
Example
int x = 5;
int y = 3;
Accessing Attributes
You can access attributes by creating an object of the class, and by using the dot syntax (.):
The following example will create an object of the Main class, with the name myObj. We use
the x attribute on the object to print its value:
Example
int x = 5;
14
public static void main(String[] args) {
System.out.println(myObj.x);
Modify Attributes
Example
int x;
myObj.x = 40;
System.out.println(myObj.x);
int x = 5;
myObj2.x = 25;
System.out.println(myObj1.x);
System.out.println(myObj2.x);
15
}
Multiple Attributes
Example
In Java, a constructor is a block of codes similar to the method. It is called when an instance of
the class is created. At the time of calling constructor, memory for the object is allocated in the
memory.
It is a special type of method which is used to initialize the object.
Every time an object is created using the new() keyword, at least one constructor is called.
It calls a default constructor if there is no constructor available in the class. In such case, Java
compiler provides a default constructor by default.
There are two types of constructors in Java: no-arg constructor, and parameterized
constructor.
16
1.8.2 Types of Java constructors
There are two types of constructors in Java:
1. Default constructor (no-arg constructor)
2. Parameterized constructor
<class_name>(){}
class ClassName {
TypeName variable1;
TypeName variable2;
17
ClassName(TypeName variable1, TypeName variable2) {
this.variable1 = variable1;
this.variable2 = variable2;
String name;
int rollNumber;
double marks;
this.name = name;
this.rollNumber = rollNumber;
this.marks = marks;
student.displayDetails();
18
}
Output
Name: John
Marks: 95.5
Methods are used to perform certain actions, and they are also known as functions.
Method Signature: Every method has a method signature. It is a part of the method declaration.
It includes the method name and parameter list.
Access Specifier: Access specifier or modifier is the access type of the method. It specifies the
visibility of the method. Java provides four types of access specifier:
o Public: The method is accessible by all classes when we use public specifier in our
application.
o Private: When we use a private access specifier, the method is accessible only in the
classes in which it is defined.
o Protected: When we use protected access specifier, the method is accessible within the
same package or subclasses in a different package.
o Default: When we do not use any access specifier in the method declaration, Java uses
default access specifier by default. It is visible only from the same package only.
o Return Type: Return type is a data type that the method returns. It may have a primitive
data type, object, collection, void, etc. If the method does not return anything, we use void
keyword.
o Method Name: It is a unique name that is used to define the name of a method. It must be
corresponding to the functionality of the method. Suppose, if we are creating a method for
subtraction of two numbers, the method name must be subtraction(). A method is invoked
by its name.
19
o Parameter List: It is the list of parameters separated by a comma and enclosed in the pair
of parentheses. It contains the data type and variable name. If the method has no parameter,
left the parentheses blank.
o Method Body: It is a part of the method declaration. It contains all the actions to be
performed. It is enclosed within the pair of curly braces.
Each and every predefined method is defined inside a class. Such as print() method is defined in
the java.io.PrintStream class. It prints the statement that we write inside the method. For
example, print("Java"), it prints Java on the console.
Demo.java
}
}
// Outputs "I just got executed!"
Addition.java
● Static Method
● Instance Method
● Abstract Method
1.9.1.5.1 Static Method
A method that has static keyword is known as static method. In other words, a method that belongs
to a class rather than an instance of a class is known as a static method. We can also create a static
method by using the keyword static before the method name.
The main advantage of a static method is that we can call it without creating an object. It can access
static data members and also change the value of it. It is used to create an instance method. It is
invoked by using the class name. The best example of a static method is the main() method.
21
Example of static method
Display.java
public class Display
{
public static void main(String[] args)
{
show();
}
static void show()
{
System.out.println("It is an example of static method.");
}
}
1.91.5.2 Instance Method
The method of the class is known as an instance method. It is a non-static method defined in the
class. Before calling or invoking the instance method, it is necessary to create an object of its class.
Let's see an example of an instance method.
Example Instance Method
InstanceMethodExample.java
public class InstanceMethodExample
{
public static void main(String [] args)
{
//Creating an object of the class
InstanceMethodExample obj = new InstanceMethodExample();
//invoking instance method
System.out.println("The sum is: "+obj.add(12, 13));
}
int s;
//user-defined method because we have not used static keyword
public int add(int a, int b)
{
s = a+b;
//returning the sum
return s;
}
}
Output:
The sum is: 25
1.91..5.3 Abstract Method
The method that does not has method body is known as abstract method. In other words, without
an implementation is known as abstract method. It always declares in the abstract class. It means
the class itself must be abstract if it has abstract method. To create an abstract method, we use the
keyword abstract.
Syntax
22
abstract void method_name();
Example of abstract method
Demo.java
abstract class Demo //abstract class
{
//abstract method declaration
abstract void display();
}
public class MyClass extends Demo
{
//method impelmentation
void display()
{
System.out.println("Abstract method?");
}
public static void main(String args[])
{
//creating object of abstract class
Demo obj = new MyClass();
//invoking abstract method
obj.display();
}
}
Output:
Abstract method...
23
Lecture No. : 4
1.10 Access Specifier in Java
1. Private: The access level of a private modifier is only within the class. It cannot be
accessed from outside the class.
2. Default: The access level of a default modifier is only within the package. It cannot be
accessed from outside the package. If you do not specify any access level, it will be the
default.
3. Protected: The access level of a protected modifier is within the package and outside the
package through child class. If you do not make the child class, it cannot be accessed from
outside the package.
4. Public: The access level of a public modifier is everywhere. It can be accessed from within
the class, outside the class, within the package and outside the package.
Private Y N N N
Default Y Y N N
Protected Y Y Y N
Public Y Y Y Y
The static keyword in Java is used for memory management mainly. We can apply static keyword
with variables, methods, blocks and nested classes. The static keyword belongs to the class than
an instance of the class.
24
o The static variable can be used to refer to the common property of all objects (which is not
unique for each object), for example, the company name of employees, college name of
students, etc.
o The static variable gets memory only once in the class area at the time of class loading.
Counter2(){
count++;//incrementing the value of static variable
System.out.println(count);
}
o A static method belongs to the class rather than the object of a class.
o A static method can be invoked without the need for creating an instance of a class.
o A static method can access static data members and can change their value of it.
Output:
If you don't want others (or yourself) to overwrite existing values, use the final keyword (this will
declare the variable as "final" or "constant", which means unchangeable and read-only):
Example
myNum = 20; // will generate an error: cannot assign a value to a final variable
26
Lecture No. : 5
1.13 Comments
Comments can be used to explain Java code, and to make it more readable. It can also be used to
prevent execution when testing alternative code.
The comments may be single-line, multi-line, and documentation comments.
o Single-line Comment: It starts with a pair of forwarding slash (//). For example:
/*It is an example of
multiline comment*/
Table 4: Data types
Data
Size Description
Type
byte 1 byte Stores whole numbers from -128 to 127
2
short Stores whole numbers from -32,768 to 32,767
bytes
4
int Stores whole numbers from -2,147,483,648 to 2,147,483,647
bytes
8 Stores whole numbers from -9,223,372,036,854,775,808 to
long
bytes 9,223,372,036,854,775,807
4
float Stores fractional numbers. Sufficient for storing 6 to 7 decimal digits
bytes
8
double Stores fractional numbers. Sufficient for storing 15 decimal digits
bytes
boolean 1 bit Stores true or false values
2
char Stores a single character/letter or ASCII values
bytes
o Documentation Comment: It starts with the delimiter (/**) and ends with */. For
example:
● Primitive data types - includes byte, short, int, long, float, double, boolean and char
● Non-primitive data types - such as String, Arrays and Classes (you will learn more about
these in a later chapter)
● String - stores text, such as "Hello". String values are surrounded by double quotes
● int - stores integers (whole numbers), without decimals, such as 123 or -123
● float - stores floating point numbers, with decimals, such as 19.99 or -19.99
● char - stores single characters, such as 'a' or 'B'. Char values are surrounded by single quotes
● boolean - stores values with two states: true or false
Example
int myNum = 5;
Type casting is when you assign a value of one primitive data type to another type.
int myInt = 9;
28
System.out.println(myInt); // Outputs 9
System.out.println(myInt); // Outputs 9
To create a variable, you must specify the type and assign it a value:
Syntax
Example
Create a variable called myNum of type int and assign it the value 15:
System.out.println(myNum)
29
Instance variables are non-static variables and are declared in a class outside of any method,
constructor, or block.
3. Static Variables
void method()
{
int n=90;//local variable
}
public static void main(String args[])
{
int data=50;//local variable
}
}//end of class
Operator in Java is a symbol that is used to perform operations. For example: +, -, *, / etc.
There are many types of operators in Java which are given below:
o Unary Operator,
o Arithmetic Operator,
o Shift Operator,
o Relational Operator,
o Bitwise Operator,
o Logical Operator,
o Ternary Operator and
o Assignment Operator.
30
Table 5: operator precedence
class Main {
boolean result;
31
System.out.println("Is str an object of String? " + result);
}
Output
Is str an object of String? true
Syntax:
if(condition){
//code to be executed
}
Syntax:
32
if(condition){
//code if condition is true
}else{
//code if condition is false
}
Syntax:
if(condition1){
//code to be executed if condition1 is true
}else if(condition2){
//code to be executed if condition2 is true
}
else if(condition3){
//code to be executed if condition3 is true
}
...
else{
//code to be executed if all the conditions are false
}
Syntax:
if(condition){
//code to be executed
if(condition){
//code to be executed
}
}
Syntax:
switch(expression){
case value1:
//code to be executed;
break; //optional
case value2:
//code to be executed;
break; //optional
33
......
default:
code to be executed if all cases are not matched;
}
If we have a for loop inside the another loop, it is known as nested for loop. The inner loop executes
completely whenever outer loop executes.
Syntax:
while (condition){
//code to be executed
I ncrement / decrement statement
}
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);
34
The Java break statement is used to break loop or switch statement. It breaks the current flow of
the program at specified condition. In case of inner loop, it breaks only inner loop.
We can use Java break statement in all types of loops such as for loop, while loop and do-while
loop.
Syntax:
break;
for(int i=1;i<=10;i++){
if(i==5){
//breaking the loop
break;
}
System.out.println(i);
}
Output:
1
2
3
4
The continue statement is used in loop control structure when you need to jump to the next iteration
of the loop immediately. It can be used with for loop or while loop.
The Java continue statement is used to continue the loop. It continues the current flow of the
program and skips the remaining code at the specified condition. In case of an inner loop, it
continues the inner loop only.
We can use Java continue statement in all types of loops such as for loop, while loop and do-while
loop.
Syntax:
continue;
for(int i=1;i<=10;i++){
if(i==5){
//using continue statement
continue;//it will skip the rest statement
}
System.out.println(i);
}
Output:
1
2
35
3
4
6
7
8
9
10
Normally, an array is a collection of similar type of elements which has contiguous memory
location.
Java array is an object which contains elements of a similar data type. Additionally, The elements
of an array are stored in a contiguous memory location. It is a data structure where we store similar
elements. We can store only a fixed set of elements in a Java array.
Array in Java is index-based, the first element of the array is stored at the 0th index, 2nd element
is stored on 1st index and so on.
36
Let's see the simple example to declare, instantiate, initialize and print the 2Dimensional array.
//Java Program to illustrate the use of multidimensional array
class Testarray3{
public static void main(String args[]){
//declaring and initializing 2D array
int arr[][]={{1,2,3},{2,4,5},{4,4,5}};
//printing 2D array
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
System.out.print(arr[i][j]+" ");
}
System.out.println();
}
}}
In Java, string is basically an object that represents sequence of char values. An array of characters
works same as Java string. For example:
char[] ch={'j','a','v','a','t','p','o','i','n','t'};
String s=new String(ch);
is same as:
String s="javatpoint";
Java String class provides a lot of methods to perform operations on strings such as
compare(), concat(), equals(), split(), length(), replace(), compareTo(), intern(), substring() etc.
1) String Literal
2) By new keyword
37
1.19.3 Java String Example
StringExample.java
public class StringExample{
public static void main(String args[]){
String s1="java";//creating string by Java string literal
char ch[]={'s','t','r','i','n','g','s'};
String s2=new String(ch);//converting char array to string
String s3=new String("example");//creating Java string by new keyword
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
}}
38
Lecture No. : 6
1.20 Java OOPs Concepts
Simula is considered the first object-oriented programming language. The programming paradigm
where everything is represented as an object is known as a truly object-oriented programming
language.
Smalltalk is considered the first truly object-oriented programming language.
The popular object-oriented languages are Java, C#, PHP, Python, C++, etc.
Object means a real-world entity such as a pen, chair, table, computer, watch, etc. Object-
Oriented Programming is a methodology or paradigm to design a program using classes and
objects.
o Object
o Class
o Inheritance
o Polymorphism
o Abstraction
o Encapsulation
Class
A class is a group of objects that have common properties. It is a template or blueprint from which
objects are created. It is a logical entity. It can't be physical.
class <class_name>{
field;
method;
Object
Any entity that has state and behavior is known as an object. For example, a chair, pen, table,
keyboard, bike, etc. It can be physical or logical.
An Object can be defined as an instance of a class.
Example: A dog is an object because it has states like color, name, breed, etc. as well as behaviors
like wagging the tail, barking, eating, etc.
Object Definitions:
39
o An object is a real-world entity.
o An object is a runtime entity.
o The object is an entity which has state and behavior.
o The object is an instance of a class.
Create an Object
In Java, an object is created from a class. We have already created the class named Main, so now
we can use this to create objects.
To create an object of Main class , specify the class name, followed by the object name, and use
the keyword new:
Inheritance
When one object acquires all the properties and behaviors of a parent object, it is known as
inheritance. It provides code reusability. It is used to achieve runtime polymorphism.
Polymorphism
If one task is performed in different ways, it is known as polymorphism. For example: to convince
the customer differently, to draw something, for example, shape, triangle, rectangle, etc.
Abstraction
Hiding internal details and showing functionality is known as abstraction. For example phone call,
we don't know the internal processing.
In Java, we use abstract class and interface to achieve abstraction.
Encapsulation
Binding (or wrapping) code and data together into a single unit are known as encapsulation. For
example, a capsule, it is wrapped with different medicines.
A java class is the example of encapsulation. Java bean is the fully encapsulated class because all
the data members are private here.
1.20.1 Top Advantages of OOP
c. Encapsulation: Protects data integrity and privacy by restricting direct access and
allowing controlled access through methods.
40
d. Flexibility and Scalability: OOP enables easy addition and modification of features
without impacting the entire codebase.
class <class_name>{
variables ;
methods;
}
Main.java
int x = 5;
41
Object
Create an Object
In Java, an object is created from a class. We have already created the class named Main, so now
we can use this to create objects.
To create an object of Main, specify the class name, followed by the object name, and use the
keyword new:
Example
int x = 5;
System.out.println(myObj.x);
Inheritance in Java is a mechanism in which one object acquires all the properties and behaviors
of a parent object.
Inheritance represents the IS-A relationship which is also known as a parent-child relationship.
42
o Reusability: As the name specifies, reusability is a mechanism which facilitates you to
reuse the fields and methods of the existing class when you create a new class. You can
use the same fields and methods already defined in the previous class.
Figure 6: Inheritance
As displayed in the above figure, Programmer is the subclass and Employee is the superclass. The
relationship between the two classes is Programmer IS-A Employee. It means that Programmer
is a type of Employee.
class Employee{
float salary=40000;
}
class Programmer extends Employee{
int bonus=10000;
public static void main(String args[]){
Programmer p=new Programmer();
System.out.println("Programmer salary is:"+p.salary);
System.out.println("Bonus of Programmer is:"+p.bonus);
}
}
Test it Now
Programmer salary is:40000.0
Bonus of programmer is:10000
In the above example, Programmer object can access the field of own class as well as of Employee
class i.e. code reusability.
43
In java programming, multiple and hybrid inheritance is supported through interface only. We will
learn about interfaces later.
File: TestInheritance.java
class Animal{
void eat(){System.out.println("eating...");}
}
class Dog extends Animal{
void bark(){System.out.println("barking...");}
}
class TestInheritance{
public static void main(String args[]){
Dog d=new Dog();
d.bark();
d.eat();
}}
Output:
barking...
eating...
44
1.21.4.2 Multilevel Inheritance Example
When there is a chain of inheritance, it is known as multilevel inheritance. As you can see in the
example given below, BabyDog class inherits the Dog class which again inherits the Animal class,
so there is a multilevel inheritance.
class Animal{
void eat(){System.out.println("eating...");}
}
class Dog extends Animal{
void bark(){System.out.println("barking...");}
}
class BabyDog extends Dog{
void weep(){System.out.println("weeping...");}
}
class TestInheritance2{
public static void main(String args[]){
BabyDog d=new BabyDog();
d.weep();
d.bark();
d.eat();
}}
Output:
weeping...
barking...
eating...
Output:
45
meowing...
eating...
Q) Why multiple inheritance is not supported in java?
To reduce the complexity and simplify the language, multiple inheritance is not supported in java.
Consider a scenario where A, B, and C are three classes. The C class inherits A and B classes. If
A and B classes have the same method and you call it from child class object, there will be
ambiguity to call the method of A or B class.
Since compile-time errors are better than runtime errors, Java renders compile-time error if you
inherit 2 classes. So whether you have same method or different, there will be compile time error.
class A{
void msg(){System.out.println("Hello");}
}
class B{
void msg(){System.out.println("Welcome");}
}
class C extends A,B{//suppose if it were
superclass, also known as parent class or base class, is the class whose properties and behaviors
are inherited by the subclass. So, if A and B are two classes and if B class inherits A class, then A
class is called the superclass.
Figure 9: Superclass
A subclass, also known as child class or derived class, inherits another class's properties and
behaviourss. So, if A and B are two classes and if B class inherits A class, then the B class is called
the subclass.
46
Figure 10: Sub class
47
Lecture No.:7
1.24 Method Overloading in Java
If a class has multiple methods having same name but different in parameters, it is known
as Method Overloading.
There are two ways to overload the method in java
1. By changing number of arguments
2. By changing the data type
In Java, Method Overloading is not possible by changing the return type of the method only.
In this example, we are creating static methods so that we don't need to create instance for calling
methods.
Example-Method Overloading using changing arguments
class Adder{
static int add(int a,int b){return a+b;}
static int add(int a,int b,int c){return a+b+c;}
}
class TestOverloading1{
public static void main(String[] args){
System.out.println(Adder.add(11,11));
System.out.println(Adder.add(11,11,11));
}}
Test it Now
Output:
22
33
class Adder{
static int add(int a, int b){return a+b;}
static double add(double a, double b){return a+b;}
}
class TestOverloading2{
public static void main(String[] args){
System.out.println(Adder.add(11,11));
System.out.println(Adder.add(12.3,12.6));
48
}}
Test it Now
Output:
22
24.9
If subclass (child class) has the same method as declared in the parent class, it is known as method
overriding in Java.
In other words, If a subclass provides the specific implementation of the method that has been
declared by one of its parent class, it is known as method overriding.
1.25.1 Rules for Java Method Overriding
1. The method must have the same name as in the parent class
2. The method must have the same parameter as in the parent class.
3. There must be an IS-A relationship (inheritance).
49
1.25.2 Overloading vs Overriding
Table 6: Method Overloading Vs Overriding
Encapsulation helps to hide data by preventing unauthorized access to the implementation details.
1.26.2 Example-Encapsulation
public class Person {
private String name;
// Getter
public String getName() {
return name;
}
// Setter
public void setName(String newName) {
this.name = newName;
}
}
Polymorphism in Java is a concept by which we can perform a single action in different ways.
Polymorphism is derived from 2 Greek words: poly and morphs. The word "poly" means many
and "morphs" means forms. So polymorphism means many forms.
There are two types of polymorphism in Java: compile-time polymorphism and runtime
polymorphism.
obj.myMethod();
}
}
class ABC{
public void myMethod()
{
System.out.println("parent method");
}
}
Output-
parent method
child method
53
Lecture No. : 8
1.28 Abstration
Data abstraction is the process of hiding certain details and showing only essential information
to the user.
Abstraction can be achieved with either abstract classes or interfaces (which you will learn more
about in the next chapter).
The abstract keyword is a non-access modifier, used for classes and methods:
● Abstract class: is a restricted class that cannot be used to create objects (to access it, it
must be inherited from another class).
● Abstract method: can only be used in an abstract class, and it does not have a body. The
body is provided by the subclass (inherited from).
}
1.28.1 Example of Abstract class with abstract method
In this example, Bike is an abstract class that contains only one abstract method run. Its
implementation is provided by the Honda class.
abstract class Bike{
abstract void run();
}
class Honda4 extends Bike{
void run(){System.out.println("running safely");}
public static void main(String args[]){
Bike obj = new Honda4();
obj.run();
}
}
Output
running safely
54
1.29 Interface in Java
interface <interface_name>{
56
1.29.6 Abstract Class Vs Interface
Table 7: Abstract class Vs Interface
1) Abstract class can have abstract and Interface can have only abstract methods.
non-abstract methods. Since Java 8, it can have default and static
methods also.
3) Abstract class can have final, non-final, Interface has only static and final variables.
static and non-static variables.
4) Abstract class can provide the Interface can't provide the implementation of
implementation of interface. abstract class.
5) The abstract keyword is used to declare The interface keyword is used to declare
abstract class. interface.
6) An abstract class can extend another An interface can extend another Java interface
Java class and implement multiple Java only.
interfaces.
8) A Java abstract class can have class Members of a Java interface are public by
members like private, protected, etc. default.
9)Example: Example:
public abstract class Shape{ public interface Drawable{
public abstract void draw(); void draw();
} }
57
Lecture No.: 9
1.30 Java Package
A package in Java is used to group related classes. Think of it as a folder in a file directory. We
use packages to avoid name conflicts, and to write a better maintainable code. Packages are divided
into two categories:
● Built-in Packages (packages from the Java API)
● User-defined Packages (create your own packages)
The Java API is a library of prewritten classes, that are free to use, included in the Java
Development Environment.
To use a class or a package from the library, you need to use the import keyword:
Syntax
Import a Class
If you find a class you want to use, for example, the Scanner class, which is used to get user
input, write the following code:
Example
import java.util.Scanner;
In the example above, java.util is a package, while Scanner is a class of the java.util package.
To use the Scanner class, create an object of the class and use any of the available methods found
in the Scanner class documentation. In our example, we will use the nextLine() method, which is
used to read a complete line:
Example
import java.util.Scanner;
58
class MyClass {
System.out.println("Enter username");
To import a whole package, end the sentence with an asterisk sign (*).
Example
import java.util.*;
To create your own package, you need to understand that Java uses a file system directory to store
them. Just like folders on your computer:
Example
59
└── root
└── mypack
└── MyPackageClass.java
MyPackageClass.java
package mypack;
class MyPackageClass {
System.out.println("This is my package!");
The -d keyword specifies the destination for where to save the class file. You can use any directory
name, like c:/user (windows), or, if you want to keep the package within the same directory, you
can use the dot sign ".", like in the example above.
Note: The package name should be written in lower case to avoid conflict with class names.
When we compiled the package in the example above, a new folder was created, called "mypack".
This is my package!
//save as Simple.java
package mypack;
public class Simple{
60
public static void main(String args[]){
System.out.println("Welcome to package");
}
}
How to compile java package
If you are not using any IDE, you need to follow the syntax given below:
javac -d directory javafilename
For example
javac -d . Simple.java
The -d switch specifies the destination where to put the generated class file. You can use any
directory name like /home (in case of Linux), d:/abc (in case of windows) etc. If you want to keep
the package within the same directory, you can use . (dot).
How to run java package program
You need to use fully qualified name e.g. mypack.Simple etc to run the class.
Output:Welcome to package
The -d is a switch that tells the compiler where to put the class file i.e. it represents destination. The .
represents the current folder.
• Select Start -> Control Panel -> System -> Advanced system setting-> Environment
Variables -> System Variables then new
61
Lecture No. : 10
1.32 Java Create Jar Files
We can either download the JAR files from the browser or can write our own JAR files
using Eclipse IDE.
The steps to bundle the source code, i.e., .java files, into a JAR are given below. In this section,
we only understand how we can create JAR files using eclipse IDE. In the following steps, we
don't cover how we can create an executable JAR in Java.
1. In the first step, we will open Eclipse IDE and select the Export option from
the File When we select the Export option, the Jar File wizard opens with the following
2. From the open wizard, we select the Java JAR file and click on the Next The Next button
opens JAR Export for J
62
Figure 18: step 3
3. Now, from the JAR File Specification page, we select the resources needed for exporting
in the Select the resources to export After that, we enter the JAR file name and folder. By
default, the Export generated class files and resources checkbox is checked. We also check
the Export Java source files and resources checkbox to export the source. If there are other
Java files or resources which we want to include and which are available in the open
project, browse to their location and ensure the file or resource is checked in the window
on the right. Code.
63
On the same page, there are three more checkboxes, i.e., Compress the content of the
JAR file, Add directory entries, and Overwrite existing files without warning. By
default, the Compress content of the JAR file checkbox is checked.
4. Now, we have two options for proceeding next, i.e., Finish and Next. If we click on
the Next, it will immediately create a JAR file to that location which we defined in
the Select the export destination. If we click on the Next button, it will open the
Jar Packaging Option wizard for creating a JAR description, setting the advance
option,anging the default manifest.
5. For now, we skip the Next and click on the Finish button.Now, we go to the specified
location, which we defined in the Select the export destination, to ensure that the JAR file is
created successfully or not.
In Java, static import concept is introduced in 1.5 version. With the help of static import, we can
access the static members of a class directly without class name or any object. For Example: we
always use sqrt() method of Math class by using Math class i.e. Math.sqrt(), but by using static
import we can access sqrt() method directly.
According to SUN microSystem, it will improve the code readability and enhance coding. But
according to the programming experts, it will lead to confusion and not good for programming. If
there is no specific requirement then we should not go for static import.
Advantage of static import:
If user wants to access any static member of class then less coding is required.
64
1.33.1 Disadvantage of static import:
Static import makes the program unreadable and unmaintainable if you are reusing this feature.
class Geeks {
System.out.println(Math.sqrt(4));
System.out.println(Math.pow(2, 2));
System.out.println(Math.abs(6.3));
Output:
2.0
4.0
For avoiding unwanted package names, we have some following naming conventions which we
use in creating a package.
o The name should always be in the lower case.
o They should be period-delimited.
o The names should be based on the company or organization name.
In order to define a package name based on an organization, we'll first reverse the company URL.
After that, we define it by the company and include division names and project names.
For example, if we want to create a package out of www.javatpoint.com, we will reserve it in the
following way:
com.javatpoint
com.javatpoint.examples
66
Questions
1. What are the features of Java?
2. What is the difference between JDK, JRE, and JVM?
3. What is the difference between a class and an object?
4. What are the four principles of OOP?
5. What are access modifiers?
6. What is encapsulation, polymorphism, abstraction?
7. What is a constructor?
8. What do you understand by an instance variable and a local variable?
9. What do you mean by data encapsulation?
10. Briefly explain the concept of constructor overloading
11. Define Copy constructor in java.
12. Explain the use of final keyword in variable, method and class.
13. When can you use super keyword?
14. Why is the main method static in Java?
15. Difference between static methods, static variables, and static classes in java.
16. What is the purpose of the static keyword in Java?
17. Explain the concept of inheritance in Java through examples
18. How do you create and use an array in Java?
19. What is method overloading in Java?
20. What is the purpose of the final keyword when used with a variable?
21. What is the difference between an abstract class and an interface?
22. What are the advantages of a java package?
23. Define Packages in Java.
24. Explain the usage of Java packages
67
UNIT-2
Lecture No. Topic name
68
Lecture No. - 11
Exception Handling
1. What is Exception Handling?
Exception handling is a programming mechanism that allows a program to gracefully respond to
and recover from errors or unexpected events (exceptions) that occur during runtime, preventing
abrupt crashes and allowing for more robust and user-friendly applications.
2. Why Exception Handling?
Exception Handling is very important in a program because they provide a way of handling errors
to ensure stability and prevent runtime error which can cause the program to crash or display
runtime error messages to the user which only the programmer should see.
3. Where Exception Handling?
In Java, you can use exception handling to manage errors and unexpected behaviours that occur
during runtime or compile time.
2.1 The Idea behind Exception –
The core idea behind exceptions is to create a controlled mechanism for handling unexpected
events that occur during program execution. These events, also called exceptions, can disrupt the
normal flow of the program and potentially lead to crashes.
Here are some key aspects of the exception concept:
● Identifying unexpected events: Exceptions represent situations that deviate from the program's
● Signaling the event: When an exception occurs, the program "throws" an exception object.
This object contains information about the error, such as its type and details.
● Handling the event: The program can define specific code blocks called "try-catch" blocks to
o The catch block specifies how to handle the exception if it occurs within the try block.
● Maintaining program flow: By using exceptions, the program can gracefully recover from
errors or provide informative messages to the user, instead of simply crashing. This helps maintain
the program's overall stability and user experience.
Overall, exceptions provide a structured approach to dealing with unexpected situations, making
programs more robust, maintainable, and user-friendly
69
2.2 What is Exception in Java?
Dictionary Meaning: Exception is an abnormal condition.
In Java, an exception is an event that disrupts the normal flow of the program. It is an object which
is thrown at runtime.
In Java, Exception is an unwanted or unexpected event, which occurs during the execution of a
program, i.e. at run time, that disrupts the normal flow of the program’s instructions. Exceptions can
be caught and handled by the program. When an exception occurs within a method, it creates an
object. This object is called the exception object. It contains information about the exception, such
as the name and description of the exception and the state of the program when the exception
occurred. Major reasons why an exception Occurs
● Invalid user input
● Device failure
● Code errors
catch.
70
2.3 Types of Exceptions
Java defines several types of exceptions that relate to its various class libraries.
Java also allows users to define their own exceptions.
● Unchecked Exception
2. User-Defined Exceptions
Let us discuss the above-defined listed exception that is as follows:
1. Built-in Exceptions
Built-in exceptions are the exceptions that are available in Java libraries. These
exceptions are suitable to explain certain error situations.
● Checked Exceptions: Checked exceptions are called compile-time exceptions
checked exceptions. The compiler will not check these exceptions at compile time.
In simple words, if a program throws an unchecked exception, and even if we
didn’t handle or declare it, the program would not give a compilation error.
Note: For checked vs unchecked exception, see Checked vs Unchecked Exceptions
2. User-Defined Exceptions:
Sometimes, the built-in exceptions in Java are not able to describe a certain situation.
In such cases, users can also create exceptions, which are called ‘user-defined
Exceptions’.
71
2.3.1 Java Exception Keywords
Java provides five keywords that are used to handle the exception. The following table describes
each.
Table 1: Try catch block
Keyword Description
Try The "try" keyword is used to specify a block where we should place an exception
code. It means we can't use try block alone. The try block must be followed by either
catch or finally.
Catch The "catch" block is used to handle the exception. It must be preceded by try block
which means we can't use catch block alone. It can be followed by finally block later.
Finally The "finally" block is used to execute the necessary code of the program. It is
executed whether an exception is handled or not.
Throws The "throws" keyword is used to declare exceptions. It specifies that there may occur
an exception in the method. It doesn't throw an exception. It is always used with
method signature.
Java Exception Handling ExampleLet's see an example of Java Exception Handling in which we
are using a try-catch statement to handle the exception.
JavaExceptionExample.java
public class JavaExceptionExample{
public static void main(String args[]){
try{
//code that may raise exception
int data=100/0;
}catch(ArithmeticException e){
System.out.println(e);
}
//rest code of the program
System.out.println("rest of the code...");
}
}OUTPUT: Exception in thread main
72
2.3.2 Java Multi-catch block
A try block can be followed by one or more catch blocks. Each catch block must
contain a different exception handler. So, if you have to perform different tasks at the
occurrence of different exceptions, use java multi-catch block.
o At a time only one exception occurs and at a time only one catch block is
executed.
o All catch blocks must be ordered from most specific to most general, i.e. catch for
73
o finally block in Java can be used to put "cleanup" code such as
class TestFinallyBlock {
public static void main(String args[]){
try{
//below code do not throw any exception
int data=25/5;
System.out.println(data);
}
//catch won't be executed
catch(NullPointerException e){
System.out.println(e);
}
//executed regardless of exception occurred or not
finally {
System.out.println("finally block is always executed");
}
74
public static void main(String args[]){
try {
System.out.println("Inside the try block");
7.//below code throws divide by zero exception
int data=25/0;
System.out.println(data);
}
//cannot handle Arithmetic type exception
//can only accept Null Pointer type exception
catch(NullPointerException e){
System.out.println(e);
}
//executes regardless of exception occured or not
finally {
System.out.println("finally block is always executed");
}
System.out.println ("rest of the code...");
}
}
Output:
75
//function to check if person is eligible to vote or not
public static void validate(int age) {
if(age<18) {
//throw Arithmetic exception if not eligible to vote
throw new ArithmeticException("Person is not eligible to vote");
}
else {System.out.println("Person is eligible to vote!!");
}
}
//main method
public static void main(String args[]){
//calling the function
validate(13);
System.out.println("rest of the code...");
}
}
Another example 1-
public class Main {
static void checkAge(int age) {
if (age < 18) {
throw new ArithmeticException("Access denied - You must be at least 18 years old.");
} else {
System.out.println("Access granted - You are old enough!");
}
}
public static void main(String[] args) {
checkAge(15);
}
}
Output-
76
Example 2-
// Java program to demonstrate
// how to throw an exception
class Geeks {
static void fun()
{
try {
throw new NullPointerException("demo");
}
catch (NullPointerException e) {
System.out.println("Caught inside fun().");
throw e; // rethrowing the exception
}
}
78
Lecture No. -12
2.4 Exceptions as Control Flow
Using exceptions as control flow is generally considered a bad practice. While exceptions are a
mechanism to stop unexpected behavior in software development, abusing them in expected
behaviors can lead to negative consequences.
This practice can reduce the performance of the code and make it less readable
Reasons to Avoid Using Exceptions as Control Flow
• Performance Impact: Using exceptions as control flow can reduce the performance of the code
as a response per unit time
• Readability: It makes the code less readable and hides the programmer's intention, which is
considered a bad practice
Alternatives to Using Exceptions for Control Flow
79
o Checked Exception: These are exceptions that occur at compile time and are
checked by the compiler.
This diagram provides a clear overview of the Java exception hierarchy and the
different types of exceptions.
Figure 3: Stack
Exit methodA(
) Exit main()
As seen from the output, the sequence of events is:
1. JVM invoke the main().
2. main()pushed onto call stack, before invoking methodA().
3. methodA()pushed onto call stack, before invoking methodB().
4. methodB()pushed onto call stack, before invoking methodC().
5. methodC() completes.
6. methodB()popped out from call stack and completes.
7. methodA()popped out from the call stack and completes.
8. main()popped out from the call stack and completes. Program exits.
suppose that we modify methodC() to carry
out a "divide-by-0" operation, which triggers
a ArithmeticException:
public static void
methodC() {
System.out.println
("Enter
methodC()");
System.out.println(1 / 0); // divide-by-0
triggers an ArithmeticException
System.out.println("Exit methodC()");
80
}
The exception message clearly shows the method call stack trace with the relevant statement
line numbers:
Enter main()
Enter methodA()
Enter
methodB()
Enter methodC()
at MethodCallStackDemo.methodC(MethodCallStackDemo.java:22) at
81
LinkageError) that rarely occur. If such an error occurs, there is little that you can do
and the program will be terminated by the Java runtime.The Exception class
describes the error caused by your program (e.g. FileNotFoundException,
IOException). These errors could be caught and handled by your program (e.g.,
perform an alternate action or do a graceful exit by closing all the files, network and
database connections).
2.6 Use of try
Certainly! Here's a diagram illustrating the use of the try...catch block in Java:
public class Main {
public static void main(String[] args) { try {
// Code that may throw an exception
int[] myNumbers = {1, 2, 3};
System.out.println(myNumbers[10]); // This line may throw an exception
} catch (Exception e) {
// Code to handle the exception
System.out.println("Something went wrong.");
} finally {
// Code that always executes, regardless of the result
System.out.println("The 'try catch' is finished.");
}
}
}
In this code:
● The try block contains the code that may throw an exception.
● The catch block is used to catch and handle the exception. It contains the code
● The finally block contains the code that always executes, regardless of whether
82
The syntax of try-catch-finally is:
try {
// main logic, uses methods that may throw Exceptions
......
} catch (Exception1 ex) {
// error handler for Exception1
......
} catch (Exception2 ex) {
// error handler for Exception1
......
} finally { // finally is optional
// clean up codes, always executed regardless of exceptions
......
}
If no exception occurs during the running of the try-block, all the catch-blocks are skipped,
and finally-block will be executed after the try-block. If one of the statements in the try-
block throws an exception, the Java runtime ignores the rest of the statements in the try-
block, and begins searching for a matching exception handler. It matches the exception type
with each of the catch-blocks sequentially. If a catch- block catches that exception class or
catches a superclass of that exception, the statement in that catch-block will be executed.
The statements in the finally-block are then executed after that catch-block. The program
continues into the next statement after the try-catch- finally, unless it is pre-maturely
terminated or branch-out.
If none of the catch-block matches, the exception will be passed up the call stack. The
current method executes the finally
clause (if any) and popped off the call stack. The caller follows the same procedures to
handle the exception.
The finally block is almost certain to be executed, regardless of whether or not exception
occurs (unless JVM encountered a severe error or a
System.exit()is called in the catchblock).
Example 1
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
public class TryCatchFinally {
public static void main(String[] args)
{
try
83
{
System.out.println("Start of the main logic");
System.out.println("Try opening a file ...");
Scanner in = new Scanner(new File("test.in"));
System.out.println("File Found, processing the file ...");
System.out.println("End of the main logic");
}
catch (FileNotFoundException ex)
{ // error handling separated from the main logic
System.out.println("File Not Found caught ...");
} finally {
// always run regardless of exception status
System.out.println("finally-block runs regardless of the state of exception");
}
// after the try-catch-finally
System.out.println("After try-catch-finally, life goes on...");
} finally { // finally is optional
// clean up codes, always executed regardless of exceptions
......
}
example 2-
public class Main {
public static void main(String[] args) {
try {
int[] myNumbers = {1, 2, 3};
System.out.println(myNumbers[10]);
} catch (Exception e) {
System.out.println("Something went wrong.");
} finally {
System.out.println("The 'try catch' is finished.");
}
}
}Output:
Something went wrong.
The 'try catch' is finished.
84
2.7 Catch
In Java, the catch keyword is used as part of the try...catch block to handle
exceptions. Here's a summary of its usage based on the provided search results:
● The catch statement allows you to define a block of code to be executed if an error
occurs in the try block. It comes in pairs with the try statement.
o Syntax:
o try
{ // Block of code to
} catch(Exception e) {
// Block of code to handle errors
}
o The catch block catches and handles the exceptions by declaring the type of
exception within the parameter. It includes the code that is executed if an exception
inside the try block occurs.
o It is used to handle uncertain conditions of a try block and must be followed by the
try block.
o Multiple catch blocks can be used with a single try block to handle different types of
exceptions.
The catch block is an essential part of exception handling in Java, allowing developers
to gracefully handle errors and prevent the abnormal termination of the program.
2.8 Finally
The finally block is used to execute important code such as releasing resources,
regardless of whether an exception is thrown or not in the try block.
Syntax of Finally Block in Java
finally {
/* Code that will be executed no matter
what is the result of try and catch blocks above it. */
}
Example of Finally Block in Java
Let's see both the cases, where an exception occurs, and where it does not occur.
1. Example of Finally block with an exception in the try block:
class Main {
85
System.out.println("Value of a = " + a);
System.out.println("Value of b = " + b);
int c = a / b;
System.out.println("a / b = " + c);
}
catch (Exception e) {
System.out.println("Exception Thrown: " + e);
}
finally {
System.out.println("Finally block executed!");
}
}
}
Output:
Value of a = 15
Value of b = 0
Exception Thrown: java.lang.ArithmeticException: / by zero
Finally block executed!
Explanation:
Try and catch blocks are the same as the above examples, but we can see that the code in the
finally block is executed.
Even if there is no occurrence of an exception, it will still be executed as shown below.
Example of Finally Block with no exceptions thrown in the try block:
class Main {
int c = a / b;
86
System.out.println("a / b = " + c);
}
catch (Exception e) {
System.out.println("Exception Thrown: " + e);
}
finally {
System.out.println("Finally block executed!");
}
}
}
Output:
Value of a = 15
Value of b = 5
a/b=3
Finally block executed!
Explanation:We can see that no exception thrown is the case in the try block, but the code in the
finally block is still executed.
87
Lecture No. -13
2.9 Throw
The throw keyword is used to explicitly throw an exception. Here's a summary of its usage
based on the provided search results:
● The throw statement is used to throw an exception explicitly within a method or
block of code.
Syntax:
throw new ExceptionType("Error
message");
o The throw statement is followed by the keyword new and the constructor of the
exception type to create and throw an instance of that exception.
o It is typically used to handle exceptional situations where the program
encounters an error or an unexpected condition.
o The exception that is thrown can be a built-in exception class provided by Java, or it
can be a custom exception class created by the programmer.
Java throw keyword Example
In this example, we have created a method named validate() that accepts an integer as a parameter. If
the age is less than 18, we are throwing the ArithmeticException otherwise print a message welcome
to vote.
File Name: TestThrow1.java
public class TestThrow1 {
//function to check if person is eligible to vote or not
public static void validate(int age) {
if(age<18) {
//throw Arithmetic exception if not eligible to vote
throw new ArithmeticException("Person is not eligible to vote");
}
else {
System.out.println("Person is eligible to vote!!");
}
}
//main method
public static void main(String args[]){
//calling the function
validate(13);
88
System.out.println("rest of the code...");
}
}
2.10 Throws in Exception Handling
throws keyword is used in method declarations to specify which exceptions are not
handled within the method but are instead propagated to the calling code to be
handled. Here's an overview of its usage:
Usage of the throws Keyword:
Syntax:
returnType methodName(parameters) throws
ExceptionType1, ExceptionType2, ... {
// Method body
}
● The throws keyword is used in the method signature to indicate that the method
may throw one or more exceptions of the specified types.
● When a method defines a throws clause, it informs the calling code that it is not
handling the specified exceptions internally, and it's the responsibility of the
calling code to handle or propagate these exceptions.
● The calling code must either handle the exceptions using a try-catch block or
declare the exceptions to be thrown further up the call stack.
Java throws Example
Let's see the example of Java throws clause which describes that checked exceptions can be
propagated by throws keyword.
Testthrows1.java
import java.io.IOException;
class Testthrows1{
void m()throws IOException{
throw new IOException("device error");//checked exception
}
void n()throws IOException{
m();
}
void p(){
try{
n();
}catch(Exception e){System.out.println("exception handled");}
}
89
public static void main(String args[]){
Testthrows1 obj=new Testthrows1();
obj.p();
System.out.println("normal flow...");
}
}
Output:
exception handled
normal flow...
90
Lecture No. -14
Types of Exception in Java
In Java, exception is an event that occurs during the execution of a program and disrupts the
normal flow of the program's instructions. Bugs or errors that we don't want and restrict our
program's normal execution of code are referred to as exceptions. In this section, we will
focus on the types of exceptions in Java and the differences between the two.
Exceptions can be categorized into two ways:
1. Built-in Exceptions
o Checked Exception
o Unchecked Exception
2. User-Defined Exceptions
91
CheckedExceptionExample.java
import java.io.*;
class CheckedExceptionExample {
public static void main(String args[]) {
FileInputStream file_data = null;
file_data = new FileInputStream("C:/Users/ajeet/OneDrive/Desktop/Hello.txt");
int m;
while(( m = file_data.read() ) != -1) {
System.out.print((char)m);
}
file_data.close();
}
}
In the above code, we are trying to read the Hello.txt file and display its data or content on
the screen. The program throws the following exceptions:
1. The FileInputStream(File filename) constructor throws the FileNotFoundException
that is checked exception.
2. The read() method of the FileInputStream class throws the IOException.
3. The close() method also throws the IOException.
Output:
92
How to resolve the error?
There are basically two ways through which we can solve these errors.
1) The exceptions occur in the main method. We can get rid from these compilation
errors by declaring the exception in the main method using the throws We only
declare the IOException, not FileNotFoundException, because of the child-parent
relationship. The IOException class is the parent class of FileNotFoundException, so
this exception will automatically cover by IOException. We will declare the exception
in the following way:
class Exception{
public static void main(String args[]) throws IOException {
...
...
}
If we compile and run the code, the errors will disappear, and we will see the data of the file.
We can also handle these exception using try-catch However, the way which we have
used above is not correct. We have to a give meaningful message for each exception
type. By doing that it would be easy to understand the error. We will use the try-catch
block in the following way:
Exception.java
import java.io.*;
class Exception{
public static void main(String args[]) {
FileInputStream file_data = null;
try{
file_data = new FileInputStream("C:/Users/ajeet/OneDrive/Desktop/programs/Hell.txt");
}catch(FileNotFoundException fnfe){
System.out.println("File Not Found!");
}int m;
93
try{
while(( m = file_data.read() ) != -1) {
System.out.print((char)m);
}
file_data.close();
}catch(IOException ioe){
System.out.println("I/O error occurred: "+ioe);
}
}
}
We will see a proper error message "File Not Found!" on the console because there
is no such file in that location.
Unchecked Exceptions
The unchecked exceptions are just opposite to the checked exceptions. The compiler
will not check these exceptions at compile time. In simple words, if a program throws
an unchecked exception, and even if we didn't handle or declare it, the program would
not give a compilation error. Usually, it occurs when the user provides bad data during
the interaction with the program.
Note: The RuntimeException class is able to resolve all the unchecked exceptions
because of the child-parent relationship.
UncheckedExceptionExample1.java
class UncheckedExceptionExample1 {
public static void main(String args[])
{
int postive = 35;
int zero = 0;
int result = positive/zero;
94
//Give Unchecked Exception here.
System.out.println(result);
}}
In the above program, we have divided 35 by 0. The code would be compiled
successfully, but it will throw an ArithmeticException error at runtime. On dividing a
number by 0 throws the divide by zero exception that is a uncheck exception.
Output:
UncheckedException1.java
class UncheckedException1 {
public static void main(String args[])
{
int num[] ={10,20,30,40,50,60};
System.out.println(num[7]);
}
}
Output:
In the above code, we are trying to get the element located at position 7, but the
length of the array is 6. The code compiles successfully, but throws the
ArrayIndexOutOfBoundsException at runtime.
95
2.12 User-defined Exception
In Java, we already have some built-in exception classes like
ArrayIndexOutOfBoundsException,NullPointerException, and
ArithmeticException. These exceptions are restricted to trigger on some predefined
conditions. In Java, we can write our own exception class by extends the Exception
class. We can throw our own exception on a particular condition using the throw
keyword. For creating a user-defined exception, we should have basic knowledge of
the try-catch block and throw keyword.
Let's write a Java program and create user-defined exception.
Difference between Checked and Unchecked Exception
Table 2: Checked Vs Unchecked Exception
S.No Checked Exception Unchecked Exception
1. These exceptions are checked at compile These exceptions are just opposite to
time. These exceptions are handled at the checked exceptions. These
compile time too. exceptions are not checked and
handled at compile time.
2. These exceptions are direct subclasses of They are the direct subclasses
exception but not extended from of the RuntimeException class.
RuntimeException class.
3. The code gives a compilation error in the The code compiles without any error
case when a method throws a checked because the exceptions escape the
exception. The compiler is not able to notice of the compiler. These
handle the exception on its own. exceptions are the results of user-
created errors in programming logic.
4. These exceptions mostly occur when the These exceptions occur mostly
probability of failure is too high. due to programming mistakes.
96
Lecture No. -15
What is java I/O?
Java I/O is used to process the input and produce the output. Java uses the concept of a stream to
make I/O operation fast. The java.io package contains all the classes required for input and
output operations.
Why Use I/O?
To take the input from input devices and show output we use I/O concepts.
Where Use I/O?
In java language, if you need to take input and output then you need to use Java I/O
Ingtroduction-
Java I/O (Input and Output) is used to process the input and produce the output.
Java uses the concept of a stream to make I/O operation fast. The java.io package contains all the
classes required for input and output operations.
Core Concepts of Java I/O
Java I/O revolves around two primary concepts: streams and readers/writers.
Streams: Streams represent a sequence of data. In Java, there are two types of streams: input
streams and output streams. Input streams are used to read data from a source, while output
streams are used to write data to a destination. Streams can be categorized into byte streams
(InputStream and OutputStream) and character streams (Reader and Writer).
Readers/Writers: Readers and writers are specialized stream classes designed for handling
character data. They provide a convenient way to read from and write to character-based data
sources. Readers read character data from input streams, while writers write character data to
output streams.
Stream
A stream is a sequence of data. In Java, a stream is composed of bytes. It's called a stream
because it is like a stream of water that continues to flow.
In Java, 3 streams are created for us automatically. All these streams are attached with the
console.
1) System.out: standard output stream
2) System.in: standard input stream
3) System.err: standard error stream
2.13 ByteStream Classes in Java
ByteStream classes are used to read bytes from the input stream and write bytes to the
output stream. In other words, we can say that ByteStream classes read/write the data
of 8- bits. We can store video, audio, characters, etc., by using ByteStream classes.
97
These classes are part of the java.io package.
The ByteStream classes are divided into two types of classes, i.e., InputStream and
OutputStream. These classes are abstract and the super classes of all the Input/Output
stream classes.
InputStream Class
The InputStream class provides methods to read bytes from a file, console or memory.
It is an abstract class and can't be instantiated; however, various classes inherit the
InputStream class and override its methods. The subclasses of InputStream class are
given in the following table.
Table 3: InputStream Class
SN Class Description
1 BufferedInputStream This class provides methods to read bytes from the buffer.
2 ByteArrayInputStream This class provides methods to read bytes from the byte
array.
3 DataInputStream This class provides methods to read Java primitive data
types.
4 FileInputStream This class provides methods to read bytes from a file.
5 FilterInputStream This class contains methods to read bytes from the other
input streams, which are used as the primary source of
data.
6 ObjectInputStream This class provides methods to read objects.
The InputStream class contains various methods to read the data from an input
stream. These methods are overridden by the classes that inherit the InputStream
class. However, the methods are given in the following table.
98
Table 4: Methods of input stream
SN Method Description
2 int read (byte This method is used to read the specified buffer length bytes
buffer []) from the input and returns the total number of bytes
successfully read. It returns -1 once the end of the input is
encountered.
3 int read (byte This method is used to read the 'nBytes' bytes from the
buffer [], int loc, buffer starting at a specified location, 'loc'. It returns the
int nBytes) total number of bytes successfully read from the input. It
returns -1 once the end of the input is encountered.
4 int available () This method returns the number of bytes that are available to
read.
5 Void This method is used to mark the current position in the input
mark(in stream until the specified nBytes are read.
t nBytes)
6 void reset () This method is used to reset the input pointer to the
previously set mark.
7 long skip (long This method is used to skip the nBytes of the input stream
nBytes) and returns the total number of bytes that are skipped.
8 void close () This method is used to close the input source. If an attempt is
made to read even after the closing, IOException is thrown
by the method.
OutputStream Class
The OutputStream is an abstract class that is used to write 8-bit bytes to the stream.
It is the superclass of all the output stream classes. This class can't be instantiated;
however, it is inherited by various subclasses that are given in the following table.
99
Table 5: OutputStream Class
SN Class Description
1 BufferedOutputStream This class provides methods to write the bytes to the buffer.
The OutputStream class provides various methods to write bytes to the output
streams. The methods are given in the following table.Example:
Table 6: Methods of OutputStream Class
SN Method Description
1 void write (int i) This method is used to write the specified single byte to the
output stream.
2 void write (byte buffer [] It is used to write a byte array to the output stream.
)
3 Void It is used to write nByte bytes to the output stream from the
write(byte buffer starting at the specified location.
s buffer[],int loc, int
nBytes)
100
4 void flush () It is used to flush the output stream and writes the pending
buffered bytes.
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class InputOutputStreamExample {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
byte content[] = "Jtp is the best website to learn new technologies".getBytes();
ByteArrayInputStream inputStream = new
ByteArrayInputStream(content);
inputStream.read(content);
File newFile = new File("/Users/MyUser/Desktop/MyNewFile.doc");
FileOutputStream outputStream = new FileOutputStream(newFile);
outputStream.write(content);
}
}
Output:
6 PipedReader This class provides methods to read characters from the connected
piped output stream.
1 int read() This method returns the integral representation of the next
character present in the input. It returns -1 if the end of the input
is encountered.
2 int read(char buffer[]) This method is used to read from the specified buffer. It returns
the total number of characters successfully read. It returns -1 if
the end of the input is encountered.
3 int read(char buffer[], This method is used to read the specified nChars from the
int loc, int nChars) buffer at the specified location. It returns the total number of
characters successfully read.
4 void mark(int nchars) This method is used to mark the current position in the input
stream until nChars characters are read.
5 void reset() This method is used to reset the input pointer to the previous set
mark.
6 long This method is used to skip the specified nChars characters from
skip(lon the input stream and returns the number of characters skipped.
g nChars)
7 boolean ready() This method returns a boolean value true if the next request of
input is ready. Otherwise, it returns false.
8 void close() This method is used to close the input stream. However, if the
program attempts to access the input, it generates IOException.
Java Writer
It is an abstract class for writing to character streams. The methods that a subclass must
implement are write(char[], int, int), flush(), and close(). Most subclasses will override some of
the methods defined here to provide higher efficiency, functionality or both.
103
Lecture No. -16
2.14 Writer Class
Writer class is used to write 16-bit Unicode characters to the output stream. The methods
of the Writer class generate IOException. Like Reader class, Writer class is also an
abstract class that cannot be instantiated; therefore, the subclasses of the Writer class are
used to write the characters onto the output stream. The subclasses of the Writer class are
given in the below table.
Table 10: Writer class
SN Class Description
5 PipedWriter This class provides methods to write the characters to the piped
output stream.
6 StringWriter This class provides methods to write the characters to the string.
To write the characters to the output stream, the Write class provides various methods
given in the following table.
Table 11: Methods of Writer class
SN Method Description
1 void write() This method is used to write the data to the output stream.
2 void write(int i) This method is used to write a single character to the output
stream.
3 Void This method is used to write the array of characters to the
write(cha output stream.
104
r buffer[])
4 void write(char buffer This method is used to write the nChars characters to the
[],int loc, int nChars) character array from the specified location.
106
Figure 5: States of Thread in its Lifecycle
2.16 Life Cycle of a Thread
There are multiple states of the thread in a lifecycle as mentioned below:
1. New Thread: When a new thread is created, it is in the new state. The thread has not yet
started to run when the thread is in this state. When a thread lies in the new state, its
code is yet to be run and hasn’t started to execute.
2. Runnable State: A thread that is ready to run is moved to a runnable state. In this
state, a thread might actually be running or it might be ready to run at any instant of
time. It is the responsibility of the thread scheduler to give the thread, time to run.
A multi-threaded program allocates a fixed amount of time to each individual thread. Each and
every thread runs for a short while and then pauses and relinquishes the CPU to another thread so
that other threads can get a chance to run. When this happens, all such threads that are ready to
run, waiting for the CPU and the currently running thread lie in a runnable state.
3. Blocked: The thread will be in blocked state when it is trying to acquire a lock but
currently the lock is acquired by the other thread. The thread will move from the
blocked state to runnable state when it acquires the lock.
4. Waiting state: The thread will be in waiting state when it calls wait() method or join()
method. It will move to the runnable state when other thread will notify or that thread
will be terminated.
5. Timed Waiting: A thread lies in a timed waiting state when it calls a method with a
time-out parameter. A thread lies in this state until the timeout is completed or until a
notification is received. For example, when a thread calls sleep or a conditional wait, it
is moved to a timed waiting state.
6. Terminated State: A thread terminates because of either of the following reasons:
● Because it exits normally. This happens when the code of the thread has been
107
entirely executed by the program.
● Because there occurred some unusual erroneous event, like a segmentation fault
or an unhandled exception.
2.17 How to Create a Thread in Java
There are two ways to create a thread:
First, you can create a thread using the thread class (extend syntax). This provides
you with constructors and methods for creating and operating on threads.
The thread class extends the object class and implements a runnable interface.
The thread class in Java is the main class on which Java’s multithreading
system is based.
Second, you can create a thread using a runnable interface. You can use this method when
you know that the class with the instance is intended to be executed by the thread itself.
The runnable interface is an interface in Java which is used to execute
concurrent thread. The runnable interface has only one method which is run().
Now let's see the syntax of both of them:
How to use the extend syntax:
public class Main extends thread { public
void test() {
System.out.println("Threads are very helpful in java");
}
}
108
Lecture No. - 18
2.18 Priority of a Thread (Thread Priority)
Each thread has a priority. Priorities are represented by a number between 1 and 10. In
most cases, the thread scheduler schedules the threads according to their priority (known
as preemptive scheduling). But it is not guaranteed because it depends on JVM
specification that which scheduling it chooses. Note that not only JVM a Java
programmer can also assign the priorities of a thread explicitly in a Java program.
Setter & Getter Method of Thread Priority
Let's discuss the setter and getter method of the thread priority.
public final int getPriority(): The java.lang.Thread.getPriority() method returns the
priority of the given thread.
public final void setPriority(int newPriority): The java.lang.Thread.setPriority()
method updates or assign the priority of the thread to newPriority. The method throws
IllegalArgumentException if the value newPriority goes out of the range, which is 1
(minimum) to 10 (maximum).
3 constants defined in Thread class:
1. public static int MIN_PRIORITY
2. public static int NORM_PRIORITY
3. public static int MAX_PRIORITY
Default priority of a thread is 5 (NORM_PRIORITY). The value of MIN_PRIORITY is
1 and the value of MAX_PRIORITY is 10.
Example of priority of a Thread:
FileName: ThreadPriorityExample.java
// Importing the required classes
import java.lang.*;
public class ThreadPriorityExample extends Thread
{
// Method 1
// Whenever the start() method is called by a thread
// the run() method is invoked
public void run()
{
// the print statement
System.out.println("Inside the run() method");
}
109
// the main method
public static void main(String argvs[])
{
// Creating threads with the help of ThreadPriorityExample class
ThreadPriorityExample th1 = new ThreadPriorityExample();
ThreadPriorityExample th2 = new ThreadPriorityExample();
ThreadPriorityExample th3 = new ThreadPriorityExample();
// We did not mention the priority of the thread.
// Therefore, the priorities of the thread is 5, the default value
// 1st Thread
// Displaying the priority of the thread
// using the getPriority() method
System.out.println("Priority of the thread th1 is : " + th1.getPriority());
// 2nd Thread
// Display the priority of the thread
System.out.println("Priority of the thread th2 is : " + th2.getPriority());
// 3rd Thread
// // Display the priority of the thread
System.out.println("Priority of the thread th2 is : " + th2.getPriority());
// Setting priorities of above threads by
// passing integer arguments
th1.setPriority(6);
th2.setPriority(3);
th3.setPriority(9);
// 6
System.out.println("Priority of the thread th1 is : " + th1.getPriority());
// 3
System.out.println("Priority of the thread th2 is : " + th2.getPriority());
// 9
System.out.println("Priority of the thread th3 is : " + th3.getPriority());
// Main thread
110
// Displaying name of the currently executing thread
System.out.println("Currently Executing The Thread : " +
Thread.currentThread().getName());
System.out.println("Priority of the main thread is : " +
Thread.currentThread().getPriority());
// Priority of the main thread is 10 now
Thread.currentThread().setPriority(10);
System.out.println("Priority of the main thread is : " +
Thread.currentThread().getPriority());
}
}
Output:
Priority of the thread th1 is : 5
Priority of the thread th2 is : 5
Priority of the thread th2 is : 5
Priority of the thread th1 is : 6
Priority of the thread th2 is : 3
Priority of the thread th3 is : 9
Currently Executing The Thread : main
Priority of the main thread is : 5
Priority of the main thread is : 10
We know that a thread with high priority will get preference over lower priority threads when it
comes to the execution of threads. However, there can be other scenarios where two threads can
have the same priority. All of the processing, in order to look after the threads, is done by the Java
thread scheduler. Refer to the following example to comprehend what will happen if two threads
have the same priority.
FileName: ThreadPriorityExample1.java
// importing the java.lang package
import java.lang.*;
public class ThreadPriorityExample1 extends Thread
{
// Method 1
// Whenever the start() method is called by a thread
// the run() method is invoked
public void run()
{
111
// the print statement
System.out.println("Inside the run() method");
}
// the main method
public static void main(String argvs[])
{
// Now, priority of the main thread is set to 7
Thread.currentThread().setPriority(7);
// the current thread is retrieved
// using the currentThread() method
// displaying the main thread priority
// using the getPriority() method of the Thread class
System.out.println("Priority of the main thread is : " +
Thread.currentThread().getPriority());
// creating a thread by creating an object of the class ThreadPriorityExample1
ThreadPriorityExample1 th1 = new ThreadPriorityExample1();
// th1 thread is the child of the main thread
// therefore, the th1 thread also gets the priority 7
// Displaying the priority of the current thread
System.out.println("Priority of the thread th1 is : " + th1.getPriority());
}
}
Output:
Priority of the main thread is : 7
Priority of the thread th1 is : 7
`Explanation: If there are two threads that have the same priority, then one can not predict which
thread will get the chance to execute first. The execution then is dependent on the thread scheduler's
algorithm (First Come First Serve, Round-Robin, etc.)
Example of IllegalArgumentException
We know that if the value of the parameter newPriority of the method getPriority() goes out of the
range (1 to 10), then we get the IllegalArgumentException. Let's observe the same with the help of
an example.
FileName: IllegalArgumentException.java
// importing the java.lang package
import java.lang.*;
public class IllegalArgumentException extends Thread
112
{
// the main method
public static void main(String argvs[])
{
// Now, priority of the main thread is set to 17, which is greater than 10
Thread.currentThread().setPriority(17);
// The current thread is retrieved
// using the currentThread() method
// displaying the main thread priority
// using the getPriority() method of the Thread class
System.out.println("Priority of the main thread is : " +
Thread.currentThread().getPriority());
}
}
When we execute the above program, we get the following exception:
Exception in thread "main" java.lang.IllegalArgumentException
at java.base/java.lang.Thread.setPriority(Thread.java:1141)
at IllegalArgumentException.main(IllegalArgumentException.java:12)
Another example-
class MyThread extends Thread
{
public void run()
{
System.out.println("Thread Running...");
}
public static void main(String[]args)
{
MyThread p1 = new MyThread();
MyThread p2 = new MyThread();
MyThread p3 = new MyThread();
p1.start();
System.out.println("P1 thread priority : " + p1.getPriority());
System.out.println("P2 thread priority : " + p2.getPriority());
System.out.println("P3 thread priority : " + p3.getPriority());
}
113
}
P1 thread priority : 5
Thread Running...
P2 thread priority : 5
P3 thread priority : 5
class MyThread extends Thread
{
public void run()
{
System.out.println("Thread Running...");
}
}
}
2.19 Synchronization in Java
Synchronization in Java is the capability to control the access of multiple threads to any
shared resource.
Java Synchronization is better option where we want to allow only one thread to access
the shared resource.
Why use Synchronization?
The synchronization is mainly used to
1. To prevent thread interference.
2. To prevent consistency problem.
Types of Synchronization
There are two types of synchronization
1. Process Synchronization
2. Thread Synchronization
Here, we will discuss only thread synchronization.
114
Thread Synchronization
There are two types of thread synchronization mutual exclusive and inter-thread
communication.
1. Mutual Exclusive
2. Synchronized method.
3. Synchronized block.
4. Static synchronization.
1. Cooperation (Inter-thread communication in java)
Mutual Exclusive
Mutual Exclusive helps keep threads from interfering with one another while sharing
data. It can be achieved by using the following three ways:
By Using Synchronized Method
1. By Using Synchronized Block
2. By Using Static Synchronization
Concept of Lock in Java
Synchronization is built around an internal entity known as the lock or monitor. Every
object has a lock associated with it. By convention, a thread that needs consistent access
to an object's fields has to acquire the object's lock before accessing them, and then
release the lock when it's done with them.
From Java 5 the package java.util.concurrent.locks contains several lock implementations.
Understanding the problem without Synchronization
In this example, there is no synchronization, so output is inconsistent. Let's see the example:
TestSynchronization1.java
class Table{
void printTable(int n){//method not synchronized
for(int i=1;i<=5;i++){
System.out.println(n*i);
try{
Thread.sleep(400);
}catch(Exception e){System.out.println(e);}
}
}
}
class MyThread1 extends Thread{
Table t;
MyThread1(Table t){
115
this.t=t;
}
public void run(){
t.printTable(5);
}
}
class MyThread2 extends Thread{
Table t;
MyThread2(Table t){
this.t=t;
}
public void run(){
t.printTable(100);
}
}
class TestSynchronization1{
public static void main(String args[]){
Table obj = new Table();//only one object
MyThread1 t1=new MyThread1(obj);
MyThread2 t2=new MyThread2(obj);
t1.start();
t2.start();
}
}
Java Synchronized Method
If you declare any method as synchronized, it is known as synchronized method.
Synchronized method is used to lock an object for any shared resource.
When a thread invokes a synchronized method, it automatically acquires the lock for that
object and releases it when the thread completes its task.
TestSynchronization2.java
//example of java synchronized method
class Table{
synchronized void printTable(int n){//synchronized method
for(int i=1;i<=5;i++){
System.out.println(n*i);
try{
116
Thread.sleep(400);
}catch(Exception e){System.out.println(e);}
}
}
}
class MyThread1 extends Thread{
Table t;
MyThread1(Table t){
this.t=t;
}
public void run(){
t.printTable(5);
}
}
class MyThread2 extends Thread{
Table t;
MyThread2(Table t){
this.t=t;
}
public void run(){
t.printTable(100);
}
}
public class TestSynchronization2{
public static void main(String args[]){
Table obj = new Table();//only one object
MyThread1 t1=new MyThread1(obj);
MyThread2 t2=new MyThread2(obj);
t1.start();
t2.start();
}
}
117
2.20 Inter-thread Communication in Java
Inter-thread communication or Co-operation is all about allowing synchronized
threads to communicate with each other.
Cooperation (Inter-thread communication) is a mechanism in which a thread is paused
running in its critical section and another thread is allowed to enter (or lock) in the same
critical section to be executed.It is implemented by following methods of Object class:
1.wait()
2.notify()
3.notifyAll()
1) wait() method
The wait() method causes current thread to release the lock and wait until either
another thread invokes the notify() method or the notifyAll() method for this object, or
a specified amount of time has elapsed.
The current thread must own this object's monitor, so it must be called from the
synchronized method only otherwise it will throw exception.
Table 12: Wait method
Method Description
public final void wait(long It waits for the specified amount of time.
timeout)throws
2) notify() method
The notify() method wakes up a single thread that is waiting on this object's
monitor. If any threads are waiting on this object, one of them is chosen to be
awakened. The choice is arbitrary and occurs at the discretion of the
implementation.
Syntax:
public final void notify()
3) notifyAll() method
Wakes up all threads that are waiting on this object's monitor.
Syntax:
118
public final void notifyAll()
The wait() method releases the lock. The sleep() method doesn't release the lock.
119
It is the non-static method It is the static method
121
Unit-3 Java New Features
122
Lecture No.:19
3.1 Functional Interfaces
3.1.1 What Functional Interfaces?
Lambda expression provides implementation of functional interface. An interface which has only one
abstract method is called functional interface. Java provides an annotation @FunctionalInterface, which
is used to declare an interface as functional interface.
3.1.2 Why to Use Functional Interfaces?
They make code more concise and readable. Functional interfaces work beautifully with lambda
expressions, enabling you to write inline functionality without the need for a separate implementation
class.
3.1.3 Where to Use Functional Interfaces?
Commonly used in scenarios that require a single method to be implemented, such as event handling,
sorting logic, or stream API operations (like filtering and mapping in Java).
3.2 Lambda Expression
3.2.1 What is Lambda Expression?
Lambda expression is a new and important feature of Java which was included in Java SE 8. It provides a
clear and concise way to represent one method interface using an expression. It is very useful in collection
library. It helps to iterate, filter and extract data from collection.
The Lambda expression is used to provide the implementation of an interface which has functional
interface. It saves a lot of code. In case of lambda expression, we don't need to define the method again
for providing the implementation. Here, we just write the implementation code.
Java lambda expression is treated as a function, so compiler does not create .class file.
3.2.2 Why use Lambda Expression?
To provide the implementation of Functional interface.
Less coding.
3.2.3 Where use Lambda Expression?
Lambda expressions are widely used in programming to simplify code by representing instances of
functional interfaces. Here's where you can use them effectively:
3.2.4 Java Lambda Expression Syntax
(argument-list) -> {body}
Java lambda expression is consisted of three components.
Argument-list: It can be empty or non-empty as well.
Arrow-token: It is used to link arguments-list and body of expression.
123
Body: It contains expressions and statements for lambda expression.
No Parameter Syntax
() -> {
//Body of no parameter lambda
}
One Parameter Syntax
(p1) -> {
//Body of single parameter lambda
}
Two Parameter Syntax
(p1,p2) -> {
//Body of multiple parameter lambda
}
Let's see a scenario where we are not implementing Java lambda expression. Here, we are
implementing an interface without using lambda expression.
Now, we are going to implement the above example with the help of Java lambda expression.
@FunctionalInterface //It is optional
interface Drawable{
public void draw();
}
//with lambda
Drawable d2=()->{
System.out.println("Drawing "+width);
};
d2.draw();
}
}
Test it Now
124
Output:
Drawing 10
A lambda expression can have zero or any number of arguments. Let's see the examples:
3.2.5 Java Lambda Expression Example: No Parameter
interface Sayable{
public String say();
}
public class LambdaExpressionExample3{
public static void main(String[] args) {
Sayable s=()->{
return "I have nothing to say.";
};
System.out.println(s.say());
}
}
Test it Now
Output:
I have nothing to say.
125
// You can omit function parentheses
Sayable s2= name ->{
return "Hello, "+name;
};
System.out.println(s2.say("Sonoo"));
}
}
Test it Now
Output:
Hello, Sonoo
Hello, Sonoo
126
3.2.8 Java Lambda Expression Example: with or without return keyword
In Java lambda expression, if there is only one statement, you may or may not use return keyword.
You must use return keyword when lambda expression contains multiple statements.
interface Addable{
int add(int a,int b);
}
127
list.add("ankit");
list.add("mayank");
list.add("irfan");
list.add("jai");
list.forEach(
(n)->System.out.println(n)
);
}
}
Test it Now
Output:
ankit
mayank
irfan
jai
128
}
}
Test it Now
Output:
I would like to say, time is precious.
129
Java lambda expression can be used in the collection framework. It provides efficient and concise way to
iterate, filter and fetch data. Following are some lambda and collection examples provided.
3.2.12 Java Lambda Expression Example: Comparator
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class Product{
int id;
String name;
float price;
public Product(int id, String name, float price) {
super();
this.id = id;
this.name = name;
this.price = price;
}
}
public class LambdaExpressionExample10{
public static void main(String[] args) {
List<Product> list=new ArrayList<Product>();
//Adding Products
list.add(new Product(1,"HP Laptop",25000f));
list.add(new Product(3,"Keyboard",300f));
list.add(new Product(2,"Dell Mouse",150f));
130
System.out.println(p.id+" "+p.name+" "+p.price);
}
}
}
Test it Now
Output:
Sorting on the basis of name...
2 Dell Mouse 150.0
1 HP Laptop 25000.0
3 Keyboard 300.0
131
list.add(new Product(4,"Nokia Lumia",15000f));
list.add(new Product(5,"Redmi4 ",26000f));
list.add(new Product(6,"Lenevo Vibe",19000f));
132
JFrame f=new JFrame();
f.add(tf);f.add(b);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLayout(null);
f.setSize(300, 200);
f.setVisible(true);
}
Output:
Output
Alice
Bob
Charlie
Key Benefits of Method References
● Improved Readability: Method references simplify the code by removing boilerplate syntax.
● Reusability: Existing methods can be directly reused, enhancing modularity.
● Functional Programming Support: They work seamlessly with functional interfaces and
lambdas.
134
Lecture No.:20
3.4 Stream API
3.4.1 What is Stream API?
Java provides a new additional package in Java 8 called java.util.stream. This package consists of classes,
interfaces and enum to allows functional-style operations on the elements. You can use stream by
importing java.util.stream package.
Methods Description
boolean allMatch(Predicate<? super T> It returns all elements of this stream which match
predicate) the provided predicate. If the stream is empty then
true is returned and the predicate is not evaluated.
135
boolean anyMatch(Predicate<? super T> It returns any element of this stream that matches
predicate) the provided predicate. If the stream is empty then
false is returned and the predicate is not evaluated.
136
Stream<T> distinct() It returns a stream consisting of the distinct
elements (according to Object.equals(Object)) of
this stream.
Stream<T> filter(Predicate<? super T> It returns a stream consisting of the elements of this
predicate) stream that match the given predicate.
137
IntStream flatMapToInt(Function<? super It returns an IntStream consisting of the results of
T,? extends IntStream> mapper) replacing each element of this stream with the
contents of a mapped stream produced by applying
the provided mapping function to each element.
Each mapped stream is closed after its contents
have been placed into this stream. (If a mapped
stream is null an empty stream is used, instead.)
void forEach(Consumer<? super T> action) It performs an action for each element of this
stream.
void forEachOrdered(Consumer<? super T> It performs an action for each element of this
action) stream, in the encounter order of the stream if the
stream has a defined encounter order.
138
Stream<T> limit(long maxSize) It returns a stream consisting of the elements of this
stream, truncated to be no longer than maxSize in
length.
<R> Stream<R> map(Function<? super T,? It returns a stream consisting of the results of
extends R> mapper) applying the given function to the elements of this
stream.
Optional<T> max(Comparator<? super T> It returns the maximum element of this stream
comparator) according to the provided Comparator. This is a
special case of a reduction.
Optional<T> min(Comparator<? super T> It returns the minimum element of this stream
comparator) according to the provided Comparator. This is a
special case of a reduction.
boolean noneMatch(Predicate<? super T> It returns elements of this stream match the
predicate) provided predicate. If the stream is empty then true
is returned and the predicate is not evaluated.
@SafeVarargs static <T> Stream<T> of(T... It returns a sequential ordered stream whose
values) elements are the specified values.
139
static <T> Stream<T> of(T t) It returns a sequential Stream containing a single
element.
Stream<T> peek(Consumer<? super T> It returns a stream consisting of the elements of this
action) stream, additionally performing the provided action
on each element as elements are consumed from the
resulting stream.
140
Stream<T> sorted(Comparator<? super T> It returns a stream consisting of the elements of this
comparator) stream, sorted according to the provided
Comparator.
142
//Adding Products
productsList.add(new Product(1,"HP Laptop",25000f));
productsList.add(new Product(2,"Dell Laptop",30000f));
productsList.add(new Product(3,"Lenevo Laptop",28000f));
productsList.add(new Product(4,"Sony Laptop",28000f));
productsList.add(new Product(5,"Apple Laptop",90000f));
List<Float> productPriceList2 =productsList.stream()
.filter(p -> p.price > 30000)// filtering data
.map(p->p.price) // fetching price
.collect(Collectors.toList()); // collecting as list
System.out.println(productPriceList2);
}
}
Output:
[90000.0]
3.5 Default Methods
3.5.1 What is Java Default Method?
Java provides a facility to create default methods inside the interface. Methods which are defined inside
the interface and tagged with default are known as default methods. These methods are non-abstract
methods.
3.5.2 Why to use Java Default Method?
1. Avoid Code Duplication: They provide a single implementation of a method, reducing
redundancy across multiple implementing classes.
2. Flexibility: Implementing classes can choose to override the default method or stick with the
provided implementation.
3. Interface vs Abstract Classes: They bridge the gap between abstract classes and interfaces by
allowing method bodies in interfaces.
3.5.3 Where to use Java Default Method?
1. Backward Compatibility: When you need to add new methods to an interface without breaking
existing implementations. Default methods provide a default implementation, so existing classes
implementing the interface don’t need to update their code.
2. Interface Evolution: They allow interfaces to evolve over time while maintaining extensibility.
143
3. Optional Behavior: When some methods are optional and shouldn't be mandatory for all
implementing classes. Classes can override default methods if needed.
In the following example, Sayable is a functional interface that contains a default and an abstract method.
The concept of default method is used to define a method with default implementation. You can override
default method also to provide more specific implementation for the method.
Let's see a simple
interface Sayable{
// Default method
default void say(){
System.out.println("Hello, this is default method");
}
// Abstract method
void sayMore(String msg);
}
public class DefaultMethods implements Sayable{
public void sayMore(String msg){ // implementing abstract method
System.out.println(msg);
}
public static void main(String[] args) {
DefaultMethods dm = new DefaultMethods();
dm.say(); // calling default method
dm.sayMore("Work is worship"); // calling abstract method
}
}
Output:
Hello, this is default method
Work is worship
144
Lecture No.:21
3.6 Static Method
3.6.1 What is Static Method?
A static method in programming is a method that belongs to the class itself, rather than any particular
instance of the class. It can be called directly on the class without creating an object of that class. Static
methods are often used for utility or helper methods that perform tasks in isolation, without needing to
access or modify the instance variables of a class.You can also define static methods inside the
interface.Static methods are used to define utility methods.
3.6.2 Where to use Static Method?
Utility or Helper Functions: Operations like mathematical calculations, string manipulations, or
date/time conversions that don't rely on instance data.
Factory Methods: Create and return objects of the class or another type without needing instance-specific
context.
Global Counters or Configuration: Maintain static variables related to the class, such as counts or shared
settings.
Class-specific Logic: Functions that solely operate within the scope of the class, for example, managing
internal constants.
3.6.3 Why to use Static Method?
No Instance Dependency: They save memory because you don't need to create an object to access the
method.
Encapsulation of Class Logic: They help organize logic that applies to the class rather than individual
objects.
Efficiency: Static methods are straightforward and faster since they don’t require the overhead of object
creation.
Accessibility: Easily accessible across the entire class and reusable.
The following example explain, how to implement static method in interface?
interface Sayable{
// default method
default void say(){
System.out.println("Hello, this is default method");
}
// Abstract method
void sayMore(String msg);
145
// static method
static void sayLouder(String msg){
System.out.println(msg);
}
}
public class DefaultMethods implements Sayable{
public void sayMore(String msg){ // implementing abstract method
System.out.println(msg);
}
public static void main(String[] args) {
DefaultMethods dm = new DefaultMethods();
dm.say(); // calling default method
dm.sayMore("Work is worship"); // calling abstract method
Sayable.sayLouder("Helloooo..."); // calling static method
}
}
Output:
Hello there
Work is worship
Helloooo...
3.7 Base64 Encode and Decode
3.7.1 What is Base64 Encode and Decode?
Java provides a class Base64 to deal with encryption. You can encrypt and decrypt your data by using
provided methods. You need to import java.util.Base64 in your source file to use its methods.
3.7.2 Why use Base64 Encode and Decode?
Safe Transmission: It ensures that binary data can be safely transferred over protocols or media that are
designed to handle text, such as HTTP, emails (SMTP), or JSON.
Preserve Data Integrity: Prevents corruption of binary data during transmission as Base64 uses only
printable characters (e.g., letters, numbers, + and /).
Avoid Special Characters: Binary data might contain characters that are misinterpreted by some systems
(like NULL bytes). Base64 removes such issues.
Readability: While not human-readable in the traditional sense, the encoded string is composed of ASCII
text characters, making it easier to work with than raw binary.
146
3.7.2 Where use Base64 Encode and Decode?
Binary Data in Text-based Systems:
● Encoding images, files, or certificates into text for storage or transmission.
● Example: Embedding an image into an HTML document using the data URI scheme.
Email Attachments (MIME):
● Used to encode attachments for email transmission in text-based protocols like SMTP.
Storing Data in Databases:
● Helpful for storing binary data in databases that don’t support binary types, as Base64 ensures the
data remains intact.
Web Development:
● Passing binary data (like images or files) in JSON or XML APIs.
● For example, uploading files to a server via a REST API often involves Base64 encoding.
Authentication:
● Base64 is used to encode credentials in Basic Authentication for HTTP requests.
147
3.7.6 Nested Classes of Base64
Table 2: Base 64 Decoder and Encoder
Class Description
Base64.Decoder This class implements a decoder for decoding byte data using the Base64 encoding
scheme as specified in RFC 4648 and RFC 2045.
Base64.Encoder This class implements an encoder for encoding byte data using the Base64
encoding scheme as specified in RFC 4648 and RFC 2045.
Methods Description
public static Base64.Decoder getDecoder() It returns a Base64.Decoder that decodes using the
Basic type base64 encoding scheme.
public static Base64.Encoder getEncoder() It returns a Base64.Encoder that encodes using the
Basic type base64 encoding scheme.
public static Base64.Decoder getUrlDecoder() It returns a Base64.Decoder that decodes using the
URL and Filename safe type base64 encoding scheme.
148
public static Base64.Encoder getUrlEncoder() It returns a Base64.Encoder that encodes using the URL
and Filename safe type base64 encoding scheme.
Methods Description
public byte[] decode(byte[] It decodes all bytes from the input byte array using the Base64 encoding
src) scheme, writing the results into a newly-allocated output byte array. The
returned byte array is of the length of the resulting bytes.
public byte[] decode(String It decodes a Base64 encoded String into a newly-allocated byte array
src) using the Base64 encoding scheme.
public int decode(byte[] src, It decodes all bytes from the input byte array using the Base64 encoding
byte[] dst) scheme, writing the results into the given output byte array, starting at
offset 0.
public ByteBuffer It decodes all bytes from the input byte buffer using the Base64 encoding
decode(ByteBuffer buffer) scheme, writing the results into a newly-allocated ByteBuffer.
public InputStream It returns an input stream for decoding Base64 encoded byte stream.
wrap(InputStream is)
Methods Description
public byte[] encode(byte[] It encodes all bytes from the specified byte array into a newly-allocated
src) byte array using the Base64 encoding scheme. The returned byte array is
of the length of the resulting bytes.
149
public int encode(byte[] It encodes all bytes from the specified byte array using the Base64
src, byte[] dst) encoding scheme, writing the resulting bytes to the given output byte array,
starting at offset 0.
public String It encodes the specified byte array into a String using the Base64 encoding
encodeToString(byte[] src) scheme.
public ByteBuffer It encodes all remaining bytes from the specified byte buffer into a newly-
encode(ByteBuffer buffer) allocated ByteBuffer using the Base64 encoding scheme. Upon return, the
source buffer's position will be updated to its limit; its limit will not have
been changed. The returned output buffer's position will be zero and its
limit will be the number of resulting encoded bytes.
public OutputStream It wraps an output stream for encoding byte data using the Base64 encoding
wrap(OutputStream os) scheme.
public Base64.Encoder It returns an encoder instance that encodes equivalently to this one, but
withoutPadding() without adding any padding character at the end of the encoded byte data.
150
Lecture No.:22
3.8 ForEach Method
3.8.1 What is foreach method?
The for-each loop in Java (also called the enhanced for loop) was introduced in Java 5 to simplify
iteration over arrays and collections. It is cleaner and more readable than the traditional for loop and is
commonly used when the exact index of an element is not required.
Example:
Below is a basic example of using the for-each loop to iterate through an array and print each element.
A for-each loop directly accesses elements without needing index variables.
3.8.2 Why to use foreach method?
Clean and Concise Syntax: The forEach method reduces boilerplate code compared to traditional for
loops.
Lambda Expressions: It works seamlessly with lambda expressions, making it easier to perform
operations on each element.
Stream API Compatibility: Often used with the Stream API for efficient data processing.
Improved Readability: It emphasizes the action being performed, rather than the mechanics of iteration.
Parallel Processing: When combined with parallel streams, it enables easy parallel processing of data.
3.8.3 Where to use foreach method?
Iterating Over Collections: When you need to process each element of a List, Set, or Map.
● Example: Printing all elements in a List.
Performing Actions on Data Streams: Use it with the Stream API to apply actions like filtering or
transformations.
● Example: Filtering names in a list and printing them.
Logging or Debugging: Great for printing out elements in a collection for debugging purposes.
Data Processing Pipelines: Fits well in a functional style of programming for chaining operations on
data.
class ForEach {
151
public static void main(String[] args) {
// Array declaration
int arr[] = { 1, 2, 3, 4, 5 };
Output
12345
Explanation: In this example, the for-each loop iterates over the array “arr" and prints each element. We
use the variable element "e" to access each value in the array, making the loop more concise compared to
using a traditional for loop with an index.
Syntax of For-each Loop
for (type var : array) {
statements using var;
}
Parameters:
● type: The data type of the elements in the array or collection.
● var: The variable that holds the current element during each iteration.
● array: The array or collection being iterated over.
3.8.4 Finding Maximum in an Array using for-each Loop
Now, let’s go through another example that finds the maximum value in an integer array using a for-each
loop.
// Java Program to find maximum in an array
// Using for-each loop
public class Maximum {
152
public static void main(String[] args) {
Output
132
3.8.5 Limitations of the For-each Loop
While the for-each loop is convenient, there are some important limitations to consider:
1. Cannot Modify Array Elements Directly
for (int num : marks) {
// only changes num, not the array element
num = num*2;
}
Explanation: The for-each loop gives a copy of each element, not a reference. So modifying the loop
variable (num in this case) does not affect the actual array or collection.
2. No Access to Index
153
for (int num : numbers) {
if (num == target) {
// do not know the index of ‘num’ here
return ???; // Index is unavailable in for-each loop
}
}
Explanation: The for-each loop does not provide access to the index of the current element. If we need
the index for any reason (e.g., in a search operation), a traditional loop would be more appropriate.
3. Single-direction Iteration Only
for (int i = numbers.length – 1; i >= 0; i–) {
System.out.println(numbers[i]); // Reverse iteration not possible with for-each
}
Explanation: The for-each loop only iterates over the elements in a forward direction. If we need to iterate
in reverse, we have to use a traditional for loop with a manually managed index.
4. Complex Conditions are Difficult to Implement
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] == arr[i]) {
// Complex conditional checks are easier in a traditional for loop
}
}
Explanation: If our logic requires checking multiple conditions or using the index in more complex ways,
the for-each loop can be limiting. In such cases, a traditional for loop offers more flexibility.
5. Performance Overhead
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 1000000; i++) list.add(i);
// Traditional loop
154
startTime = System.currentTimeMillis();
for (int i = 0; i < list.size(); i++) { int a = list.get(i); }
endTime = System.currentTimeMillis();
System.out.println(“Traditional loop: ” + (endTime – startTime) + ” ms”);
The for-each loop sometimes might be slower compared to traditional for loops because for iterating over
collections it uses an iterator internally.
3.9 Try-with-resources
3.9.1 What is Try-with-resources?
In Java, the try-with-resources statement is a try statement that declares one or more resources. The
resource is as an object that must be closed after finishing the program. The try-with-resources statement
ensures that each resource is closed at the end of the statement execution.
You can pass any object that implements java.lang.AutoCloseable, which includes all objects which
implement java.io.Closeable.
3.9.2 Why to use Try-with-resources?
Automatic Resource Management:
● It automatically calls the close() method on resources that implement the AutoCloseable interface,
saving developers from explicitly closing them.
● Reduces boilerplate code for resource cleanup.
Exception Safety:
● Ensures that resources are closed even in the event of an exception, reducing the risk of resource
leaks.
Readability:
● Makes code more concise and easier to read.
Error Handling:
● Supports suppression of secondary exceptions during resource closing, making it easier to handle
exceptions effectively.
155
● Automatically closes connections to avoid exhausting database connections.
Input/Output Streams:
● When working with InputStream, OutputStream, Reader, Writer, and their subclasses.
Sockets and Networking:
● Handling network connections using Socket or ServerSocket.
Custom AutoCloseable Resources:
● Any custom resource that implements AutoCloseable or Closeable.
The following example writes a string into a file. It uses an instance of FileOutputStream to write data
into the file. FileOutputStream is a resource that must be closed after the program is finished with it. So,
in this example, closing of resource is done by itself try.
3.9.4 Try-with-resources
import java.io.FileOutputStream;
public class TryWithResources {
public static void main(String args[]){
// Using try-with-resources
try(FileOutputStream fileOutputStream =newFileOutputStream("abc.txt")){
String msg = "Welcome to javaTpoint!";
byte byteArray[] = msg.getBytes(); //converting string into byte array
fileOutputStream.write(byteArray);
System.out.println("Message written to file successfuly!");
}catch(Exception exception){
System.out.println(exception);
}
}
}
Output:
Message written to file successfuly!
Output of file
Welcome to javaTpoint!
156
Lecture No.:23
3.10 Type Annotations
3.10.1 What is Java Type Annotations?
Java 8 has included two new features repeating and type annotations in its prior annotations topic. In early
Java versions, you can apply annotations only to declarations. After releasing of Java SE 8 , annotations
can be applied to any type use. It means that annotations can be used anywhere you use a type. For
example, if you want to avoid NullPointerException in your code, you can declare a string variable like
this:
@NonNull String str;
Following are the examples of type annotations:
1. @NonNull List<String>
2. List<@NonNull String> str
3. Arrays<@NonNegative Integer> sort
4. @Encrypted File file
5. @Open Connection connection
6. void divideInteger(int a, int b) throws @ZeroDivisor ArithmeticException
Note - Java created type annotations to support improved analysis of Java programs. It supports way of
ensuring stronger type checking.
3.10.2 Where to use Java Type Annotations?
Method Parameters: To specify constraints or qualities about inputs.
● Example: @NonNull or @Nullable annotations to enforce null-safety.
Return Types: To describe additional details about the data being returned, such as immutability or
validation rules.
● Example: Use @Immutable to indicate that an object cannot be modified after it's created.
Generic Types: When working with collections or parameters, type annotations provide clarity.
● Example: List<@NonNull String> names;
Type Casts: Help document or validate assumptions when performing type casting.
● Example: (@NonNull String) someVariable
Throws Clause: Specify exceptions with type annotations for better clarity and tool integration.
● Example: void read() throws @Critical IOException
3.10.3 Why to use Type Annotations?
1. Enhanced Code Quality: Type annotations improve readability and make code self-documenting.
157
2. Static Analysis: Tools like Checker Framework or SpotBugs use type annotations to enforce rules
at compile-time, reducing runtime errors.
3. Null Safety: By using annotations like @NonNull, you can prevent NullPointerException at
compile-time.
4. Validation: Frameworks can perform advanced validation based on annotations, ensuring runtime
constraints are met.
5. Interoperability: They provide additional metadata for frameworks or libraries, which can use
them for processing or configuration.
6. Consistency: Annotations standardize the documentation and constraints for your types across the
codebase.
3.11 Repeating Annotations
3.11.1 What is Java Repeating Annotations?
In Java 8 release, Java allows you to repeating annotations in your source code. It is helpful when you
want to reuse annotation for the same class. You can repeat an annotation anywhere that you would use a
standard annotation.
3.11.2 Why Use Repeating Annotations?
1. Avoid Redundancy: Instead of creating a wrapper annotation to hold multiple values, you can
directly use the same annotation multiple times.
2. Improved Readability: Code becomes cleaner and easier to understand compared to using a
single annotation with complex parameters.
3. Metadata-rich Configurations: Useful in scenarios where multiple behaviors, configurations, or
metadata need to be defined on a single element.
4. Support for Frameworks/Tools: Many frameworks and libraries, such as JPA and Spring, make
use of repeating annotations for configuration.
3.11.3 Where to Use Repeating Annotations?
1. Defining Multiple Rules or Constraints:
○ For example, applying multiple validation rules to a single field.
2. Mapping or Configuration:
○ In frameworks like JPA, you can use repeating annotations to define multiple mappings.
○ Example: @JoinColumn for defining multiple foreign key relationships.
3. Event Handlers:
○ Define multiple event listeners for the same method.
4. Custom Processing:
158
○ Custom annotations that need to be processed by libraries, tools, or compilers.
For compatibility reasons, repeating annotations are stored in a container annotation that is automatically
generated by the Java compiler. In order for the compiler to do this, two declarations are required in your
code.
1. Declare a repeatable annotation type
2. Declare the containing annotation type
159
import java.lang.annotation.RetentionPolicy;
// Declaring repeatable annotation type
@Repeatable(Games.class)
@interfaceGame{
String name();
String day();
}
// Declaring container for repeatable annotation type
@Retention(RetentionPolicy.RUNTIME)
@interfaceGames{
Game[] value();
}
// Repeating annotation
@Game(name = "Cricket", day = "Sunday")
@Game(name = "Hockey", day = "Friday")
@Game(name = "Football", day = "Saturday")
public class RepeatingAnnotationsExample {
public static void main(String[] args) {
// Getting annotation by type into an array
Game[] game = RepeatingAnnotationsExample.class.getAnnotationsByType(Game.class);
for (Gamegame2 : game) { // Iterating values
System.out.println(game2.name()+" on "+game2.day());
}
}
}
OUTPUT:
Cricket on Sunday
Hockey on Friday
Football on Saturday
160
Lecture No.:24
3.12 Java Module System
3.12.1 What is Java Module System?
Java Module System is a major change in Java 9 version. Java added this feature to collect Java packages
and code into a single unit called module.
3.12.2 Why to use Java Module System?
In earlier versions of Java, there was no concept of module to create modular Java applications, that why
size of application increased and difficult to move around. Even JDK itself was too heavy in size, in Java
8, rt.jar file size is around 64MB.
To deal with situation, Java 9 restructured JDK into set of modules so that we can use only required
module for our project.
Apart from JDK, Java also allows us to create our own modules so that we can develop module based
application.
3.12.3 Where to use Java Module System?
Large Applications:
● When your application grows in size and complexity, modularity helps you organize the code into
logical, independent units.
● Example: Divide the application into modules like payment, user-management, and inventory.
Library Development:
● When creating reusable libraries, modules provide clear boundaries and hide internal
implementation details from clients, exposing only what's necessary.
Dependency Management:
● Helps in managing dependencies explicitly and avoids issues like "classpath hell" in traditional
Java applications.
● Example: You can specify dependencies for a module using the requires directive.
Security and Encapsulation:
● Use modules to hide internal implementation details and expose only public APIs through exports.
This improves the security of the application by reducing the attack surface.
Performance Optimization:
● Applications benefit from reduced memory and startup time as unused modules can be excluded
during runtime using the modular java.base or custom configurations.
The module system includes various tools and options that are given below.
161
o Includes various options to the Java tools javac, jlink and java where we can specify module
paths that locates to the location of module.
o Modular JAR file is introduced. This JAR contains module-info.class file in its root folder.
o JMOD format is introduced, which is a packaging format similar to JAR except it can include
native code and configuration files.
o The JDK and JRE both are reconstructed to accommodate modules. It improves performance,
security and maintainability.
o Java defines a new URI scheme for naming modules, classes and resources.
3.12.4 Java 9 Modularized JDK
162
It is a name of module and should follow the reverse-domain-pattern. Like we name packages, e.g.
com.javatpoint.
3.12.7 How to create Java module
Creating Java module required the following steps.
o Create a directory structure
o Create a module declarator
o Java source code
3.12.8 Create a Directory Structure
To create module, it is recommended to follow given directory structure, it is same as reverse-domain-
pattern, we do to create packages / project-structure in Java.
Note: The name of the directory containing a module's sources should be equal to the name of the module, e.g.
com.javatpoint.
Create a file module-info.java, inside this file, declare a module by using module identifier and provide
module name same as the directory name that contains it. In our case, our directory name is
com.javatpoint.
module com.javatpoint{
}
Leave module body empty, if it does not has any module dependency. Save this file
inside src/com.javatpoint with module-info.java name.
3.12.9 Java Source Code
Now, create a Java file to compile and execute module. In our example, we have a Hello.java file that
contains the following code.
class Hello{
public static void main(String[] args){
System.out.println("Hello from the Java module");
}
}
Save this file inside src/com.javatpoint/com/javatpoint/ with Hello.java name.
163
3.12.10 Compile Java Module
To compile the module use the following command.
1. javac -d mods --module-source-path src/ --module com.javatpoint
After compiling, it will create a new directory that contains the following structure.
Let's see an example, in which we are using diamond operator with inner class without specifying type.
3.13.2 Where to Use Anonymous Inner Classes
1. Event Handling:
○ Commonly used in GUI-based applications (e.g., JavaFX, Swing) to handle button clicks
or other events.
○ Example: Implementing an ActionListener for a button.
2. Implementing Functional Interfaces:
○ Useful for providing quick, concrete implementations of interfaces, especially when only
one method needs to be overridden.
○ Example: Implementing the Runnable interface for multi-threading.
3. Short-Lived Custom Implementations:
○ When you need a unique implementation of a class or interface for a specific task, and it
doesn’t make sense to create a separate named class.
4. Simplifying Code in Small Scopes:
○ Reduces boilerplate code, making your implementation shorter and more localized,
especially within methods.
3.13.3 Why Use Anonymous Inner Classes
1. Convenience:
○ Eliminates the need to create separate named classes for one-off use cases.
2. Encapsulation:
○ The logic specific to one purpose is encapsulated in one place, improving code
organization.
3. Readability:
○ Reduces clutter in the code by directly implementing behavior where it's needed.
4. Flexibility:
○ Allows you to override methods of abstract classes or interfaces directly at the point of
usage.
165
3.13.4 Java 9 Anonymous Inner Classes Example
abstract class ABCD<T>{
abstract T show(T a, T b);
}
public class TypeInferExample {
public static void main(String[] args) {
ABCD<String> a = new ABCD<>() { // diamond operator is empty, compiler infer type
String show(String a, String b) {
return a+b;
}
};
String result = a.show("Java","9");
System.out.println(result);
}
}
Output:
Java9
Although we can specifying type in diamond operator explicitly and compiler does not produce any error
message. See, the following example, type is specified explicitly.
Java 9 Anonymous Inner Classes Example
abstract class ABCD<T>{
abstract T show(T a, T b);
} public class TypeInferExample {
public static void main(String[] args) {
ABCD<String> a = new ABCD<String>() { // diamond operator is not empty
String show(String a, String b) {
return a+b;
} };
String result = a.show("Java","9");
System.out.println(result);
}
}
And we get the same result.Output:Java9
166
Lecture No.:25
3.14 Local Variable Type Inference
3.14.1 What is type inference?
Type inference is a feature of Java which provides ability to compiler to look at each method invocation
and corresponding declaration to determine the type of arguments.
3.14.2 Why to use Local Variable Type Inference?
1. Concise Code: Reduces verbosity, making the code cleaner and easier to read.
○ Example: Instead of writing HashMap<Integer, String> map = new HashMap<>();, you
can write var map = new HashMap<>();.
2. Improved Maintainability: When variable types change, you only need to modify the
assignment, not the declaration.
3. Developer Productivity: Speeds up coding by eliminating the need to repeatedly specify variable
types.
4. Enhanced Focus: Lets developers concentrate on the logic rather than the type declaration.
3.14.3 Where to use Local Variable Type Inference?
Local Variable Type Inference (var) should be used in the following cases:
1. Simplifying Code with Generics or Complex Types:
○ Example: var map = new HashMap<Integer, String>(); is cleaner than explicitly declaring
the type.
2. Iterating Collections or Arrays:
○ Example: In enhanced for loops: for (var item : items) { ... }.
3. Temporary Variables in Methods:
○ Use var for variables with a limited and clear scope: var result = someMethod();.
4. Lambda Expressions or Anonymous Classes:
○ Example: var thread = new Thread(() -> System.out.println("Hello!"));.
5. Readable and Obvious Initializations:
○ Use var when the type is evident: var text = "Hello"; // Clearly a String.
Here, we are creating arraylist by mentioning integer type explicitly at both side. The following approach
is used earlier versions of Java.
1. List<Integer> list = new ArrayList<Integer>();
In the following declaration, we are mentioning type of arraylist at one side. This approach was introduce
in Java 7. Here, you can left second side as blank diamond and compiler will infer type of it by type of
reference variable.
167
3.15 Switch Expressions
3.15.1 What is switch expressions?
The switch statement in Java is a multi-way branch statement. In simple words, the Java switch
statement executes one statement from multiple conditions.
It is an alternative to an if-else-if ladder statement. It provides an easy way to dispatch execution to
different parts of code based on the value of the expression. The expression can be of
type byte, short, char, int, long, enums, String, or wrapper classes (Integer, Short, Byte, Long).
3.15.2 Where to Use Switch Expressions?
1. Mapping Values to Results:
○ When you need to return a value based on multiple conditions without writing repetitive
code.
○ Example: Matching days of the week to activity schedules.
2. Cleaner Conditional Logic:
○ Suitable for cases where you have a large number of conditions (case values) and need
concise logic.
3. Reducing Boilerplate:
○ Use switch expressions for scenarios where a switch statement requires many break or
return keywords.
4. Functional Style Programming:
○ Perfect for modern Java's functional programming style, as switch expressions return
values directly.
5. Use with Enums:
○ Ideal when working with enums to associate specific behavior or values with each enum
constant.
3.15.3 Why Use Switch Expressions?
1. Simpler Syntax:
○ Switch expressions reduce verbosity and make code more readable. They automatically
return values, unlike the traditional switch statement.
2. Improved Safety:
○ Eliminate fall-through errors by using the -> syntax, ensuring each case is self-contained.
3. Enhanced Maintainability:
○ Easier to refactor and maintain compared to long if-else chains or verbose switch
statements.
168
4. Reduced Bugs:
○ By removing the need for break statements, switch expressions reduce accidental fall-
through bugs.
Note: Java switch expression must be of byte, short, int, long(with its Wrapper type), enums and string.
Beginning with JDK7, it also works with enumerated types (Enums in java), the String class, and Wrapper
classes.
Syntax:
switch(expression)
{
case value1 :
// Statements
break; // break is optional
case value2 :
// Statements
break; // break is optional
....
....
....
default :
// default Statement
}
Example: Size Printer Example
public class SizePrinter {
switch (sizeNumber) {
case 1:
System.out.println("Extra Small");
169
break;
case 2:
System.out.println("Small");
break;
case 3:
System.out.println("Medium");
break;
case 4:
System.out.println("Large");
break;
case 5:
System.out.println("Extra Large");
break;
default:
System.out.println("Invalid size number");
}
}
}
Output
Small
3.15.4 Some Important Rules for Java Switch Statements
● Case values must be constants or literals and of the same type as the switch expression.
● Duplicate case values are not allowed.
● The break statement is used to exit from the switch block. It is optional but recommended to
prevent fall-through.
● The default case is optional and executes if no case matches the switch expression. It can appear
anywhere within the switch block.
Note: Starting from Java 7, switch statements can use String type values. They can also handle wrapper
classes like Integer, Short, Byte, Long.
3.15.5 Flowchart of Switch-Case Statement
This flowchart shows the control flow and working of switch statements:
170
Figure 3 Flow chart of Switch Expression
Note: Java switch statement is a fall through statement that means it executes all statements if break
keyword is not used, so it is highly essential to use break keyword inside each case.
Example: Finding Day
Consider the following Java program, it declares an int named day whose value represents a day(1-7). The
code displays the name of the day, based on the value of the day, using the switch statement.
// Java program to Demonstrate Switch Case
// with Primitive(int) Data Type
// Class
public class GFG {
171
// Main driver method
public static void main(String[] args)
{
int day = 5;
String dayString;
// Case
case 1:
dayString = "Monday";
break;
// Case
case 2:
dayString = "Tuesday";
break;
// Case
case 3:
dayString = "Wednesday";
break;
// Case
case 4:
dayString = "Thursday";
break;
// Case
case 5:
dayString = "Friday";
172
break;
// Case
case 6:
dayString = "Saturday";
break;
// Case
case 7:
dayString = "Sunday";
break;
// Default case
default:
dayString = "Invalid day";
}
System.out.println(dayString);
}
}
Output
Friday
3.15.6 Break in switch case Statements
A break statement is optional. If we omit the break, execution will continue into the next case.
It is sometimes desirable to have multiple cases without “break” statements between them. For instance,
let us consider the updated version of the above program, it also displays whether a day is a weekday or a
weekend day.
173
Lecture No.:26
3.16 Yield Keyword
3.16.1 What is yield keyword?
The ‘yield’ keyword enhances the switch expressions by allowing the expression to produce a result
directly. Let us understand with an example.
In the following program, the switch expression evaluates the variable ‘day‘ value.
● If ‘day’ matches any of the weekday (MON through FRI), it prints “It is WeekDay” to the console
and sets the boolean result to true.
● If ‘day’ matches SAT or SUN, it prints “It is Weekend” to the console and sets the boolean result
to false.
● The true and false values are implicitly returned as results for the corresponding cases.
Program without 'yield' Keyword
Boolean result = switch(day) {
In earlier releases of the JDK, embedding multi-line code snippets required a tangled mess of explicit line
terminators, string concatenations, and delimiters. Text blocks eliminate most of these obstructions,
allowing you to embed code snippets and text sequences more or less as-is.
A text block is an alternative form of Java string representation that can be used anywhere a traditional
double-quoted string literal can be used. Text blocks begin with a “”” (3 double-quote marks) observed
through non-obligatory whitespaces and a newline. For example:
176
// Using a literal string
String text1 = "Geeks For Geeks";
3.18 Records
3.18.1 What is records?
In Java, a record is a special type of class declaration aimed at reducing the boilerplate code. Java records
were introduced with the intention to be used as a fast way to create data carrier classes, i.e. the classes
whose objective is to simply contain data and carry it between modules, also known as POJOs (Plain Old
Java Objects) and DTOs (Data Transfer Objects). Record was introduced in Java SE 14 as a preview
feature, which is a feature whose design, implementation, and specification are complete but it is not a
permanent addition to the language, which means that the feature may or may not exist in the future
versions of the language. Java SE 15 extends the preview feature with additional capabilities such as local
record classes.
177
3.18.2 Why Use Records?
1. Boilerplate Reduction: Records automatically generate constructors, toString, equals, and
hashCode, saving development time.
2. Immutability: Fields in a record are final by default, promoting safer and predictable code.
3. Enhanced Readability: Clear and concise definition makes code easier to understand.
4. Pattern Matching: Seamlessly integrates with Java's pattern matching features, enhancing
versatility in conditional logic.
3.18.3 Where to Use Records?
1. DTOs (Data Transfer Objects): Perfect for objects used to transfer structured data without
behavior.
2. Configurations: Ideal for representing fixed, immutable settings or parameters.
3. Aggregated Data: Combine multiple values or fields into a single encapsulated object.
4. API Responses: Represent results from external services or APIs clearly and concisely.
Let us first do discuss why we need records prior to implementing them. Let us consider an illustration
for this.
Illustration:
Consider a simple class Employee, whose objective is to contain an employee’s data such as its ID and
name and act as a data carrier to be transferred across modules. To create such a simple class, you’d need
to define its constructor, getter, and setter methods, and if you want to use the object with data structures
like HashMap or print the contents of its objects as a string, we would need to override methods such as
equals(), hashCode(), and toString().
Now let’s look at what it would take to create a similar class using Record to get its usage prior to
discussing properties of a records which are given below:
Some more Properties of Records
● You can use nested classes and interfaces inside a record.
● You can have nested records too, which will implicitly be static.
● A record can implement interfaces.
● You can create a generic record class.
● It is possible to use local record classes (since Java SE 15).
● Records are serializable.
178
As tempting as it might be to use records for data carrier objects, records are still a preview feature in
Java. Furthermore, as they are intended to be used only as a carrier of data, defining our own access
methods and other instance methods would defy the purpose. Records can be used to reduce the work
done by the developer, but internally the performance difference between a record and a class is not that
wide
public record Employee(int id, String firstName, String lastName) {}
// Creating Employee object and showcasing its use cases
// Main class
class GFG {
179
Java 15 introduced the concept of sealed classes. It is a preview feature. Java sealed classes and interfaces
restrict that which classes and interfaces may extend or implement them.
In other words, we can say that the class that cannot be inherited but can be instantiated is known as the
sealed class. It allows classes and interfaces to have more control over their permitted subtypes. It is useful
both for general domain modeling and for building a more secure platform for libraries.
3.19.2 Why to use of Sealed Class?
Sealed classes work well with the following:
o Java Reflection API
o Java Records
o Pattern Matching
3.19.3 Where to Use Sealed Classes?
1. Domain Models: Perfect for modeling fixed sets of related types, such as specific kinds of shapes
(e.g., Circle, Square, Triangle).
2. API Design: When designing APIs that should expose limited extension capabilities.
3. Enum-like Structures: Useful when you need functionality similar to enums but with more
flexibility.
4. Complex Inheritance: Manage intricate hierarchies with clear rules and constraints.
3.19.4 Advantages of Sealed Class and Interface
o It allows permission to the subclasses that can extend the sealed superclass.
o It makes superclass broadly accessible but not broadly extensible.
o It allows compilers to enforce the type system on the users of the class.
o Developer of a superclass gets control over the subclasses. Hence, they can define methods in a
more restricted way.
3.19.5 Defining a Sealed Class
The declaration of a sealed class is not much complicated. If we want to declare a class as sealed, add
a sealed modifier to its declaration. After the class declaration and extends and implements clause,
add permits clause. The clause denotes the classes that may extend the sealed class.
It presents the following modifiers and clauses:
o sealed: It can only be extended by its permitted subclasses.
o non-sealed: It can be extended by unknown subclasses; a sealed class cannot prevent its permitted
subclasses from doing this.
o permits: It allows the subclass to inherit and extend.
o final: The permitted subclass must be final because it prevents further extensions.
180
For example, the following declaration of Subjects class specifies four permitted subclasses, English,
Science, Mathematics, and Physics.
//declaration of the sealed class
public sealed class Subjects
permits English, Science, Mathematics, Physics {
}
Let's define the four permitted subclasses, English, Science, Mathematics, and Physics, in
the same module or package in which the sealed class is defined.
public sealed class Subjects
permits English, Science, Mathematics, Physics {
}
public final class English extends Subjects {
public double percentage;
}
public non-sealed class Science extends Subjects {
public String grade;
}
public sealed class Mathematics extends Subjects permits AppliedMathematics {
public double percentage;
public String grade;
}
public final class AppliedMathematics extends Mathematics {
public int marks;
public String grade;
public double percentage;
}
public non-sealed class Physics extends Subjects {
public int marks;
}
181
Questions
1. What is the use of lamda expression? Write its syntax.
2. Differentiate between yield and return keyword.
3. What do you meant by Encode64 and decode?
4. Define annotation and its types.
5. What do you meant by sealed classes? Explain with the help of program.
6. What is the use of default and static method?
7. What is the use of try with resources?
8. What do you meant by StreamAPI?
9. How to use lamda expression for thread? Write a program for same.
10. Define method reference.
182
Unit-4
Lecture No. Topic Description
183
Lecture No. 27:
4.1: Collection in Java
4.1.1 What is Collection in Java?
A Collection represents a single unit of objects, i.e., a group.
o It provides readymade architecture.
o It represents a set of classes and interfaces.
4.1.2 Why use Collection in Java?
The Collection in Java is a framework that provides an architecture to store and manipulate the
group of objects.
Java Collections can achieve all the operations that you perform on a data such as searching, sorting,
insertion, manipulation, and deletion.
Java Collection means a single unit of objects. Java Collection framework provides many
interfaces (Set, List, Queue, Deque) and classes (ArrayList, Vector, LinkedList, PriorityQueue,
HashSet, LinkedHashSet, TreeSet).
4.2: Collection Framework in Java
4.2.1 What is Collection framework?
The Collection framework represents a unified architecture for storing and manipulating a
group of objects. It has:
1. Interfaces and its implementations, i.e., classes
2. Algorithm
4.2.2. Why use Java collection framework?
The Java collections framework provides various data structures and algorithms that can be used
directly. This has two main advantages:
•We do not have to write code to implement these data structures and algorithms manually.
•Our code will be much more efficient as the collections framework is highly optimized.
4.2.3 How to use Java Collection Framework?
1.First import package import java.util.*;
2.create object of class.
3. Use methods to work with data structure
184
4.2.4 Explain the various interfaces used in the Collection framework.
The collection framework has several interfaces, each of which is used to store a different sort of
data. The interfaces included in the framework are listed below.
1. Iterable Interface: This is the collection framework's primary interface. The iterable interface is
extended by the collection interface. As a result, all interfaces and classes implement this interface
by default. This interface's main purpose is to provide an iterator for the collections. As a result, this
interface only has one abstract method, the iterator.
2. Collection Interface: The collection framework's classes implement this interface, which extends
the iterable interface. This interface covers all of the basic methods that every collection has, such as
adding data to the collection, removing data from the collection, clearing data, and so on. All of these
methods are incorporated in this interface because they are used by all classes, regardless of their
implementation style. Furthermore, including these methods in this interface guarantees that the
method names are consistent across all collections. In summary, we may conclude that this interface
lays the groundwork for the implementation of collection classes.
3. List Interface: The collection interface has a child interface called the list interface. This interface
is devoted to list data, in which we can store all of the objects in an ordered collection. This also
allows for the presence of redundant data. Various classes, such as ArrayList, Vector, Stack, and
others, implement this list interface.
4. Queue Interface: A queue interface, as the name implies, follows the FIFO (First In First Out)
order of a real-world queue line. This interface is for storing all elements in which the order of the
elements is important. When we try to shop at a store, for example, the bills are issued on a first-
come, first-served basis. As a result, the individual whose request is first in line receives the bill first.
PriorityQueue, Deque, ArrayDeque, and other classes are available.
5. Deque Interface: It differs slightly from the queue data structure. Deque, also known as a double-
ended queue, is a data structure in which elements can be added and removed from both ends. The
queue interface is extended by this interface. ArrayDeque is the class that implements this interface.
6. Set Interface: A set is an unordered group of objects in which duplicate values cannot be kept.
This collection is utilised when we want to avoid duplication of things and only keep the ones that
are unique. Various classes, such as HashSet, TreeSet, LinkedHashSet, and others, implement this
set interface.
7. Sorted Set Interface: This interface resembles the set interface in appearance. The only difference
is that this interface provides additional methods for maintaining element ordering. The sorted set
interface is an extension of the set interface that is used to manage sorted data. TreeSet is the class
185
that implements this interface. We can create a SortedSet object using this class because it
implements the SortedSet interface.
186
Lecture No. 28:
4.3 Hierarchy of Collection Framework
4.3.1 What is Hierarchy of Collection Framework?
Collection Hierarchy in Java defines the relationships among various interfaces and classes that build
up the Collections framework. It enables programmers to efficiently store, manipulate, and process
data structures in Java.
The hierarchy of the entire collection framework consists of four core interfaces such as Collection,
List, Set, Map, and two specialized interfaces named SortedSet and SortedMap for sorting.
All the interfaces and classes for the collection framework are located in java.util package. The
diagram of Java collection hierarchy is shown in the below figure.
Iterator interface provides the facility of iterating the elements in a forward direction only.
187
In Java, the Iterator interface provides a way to access elements of a collection
sequentially, allowing you to traverse and process them one at a time without exposing
the underlying collection's implementation.
The Iterable interface is the root interface for all the collection classes. The Collection interface
extends the Iterable interface and therefore all the subclasses of Collection interface also implement
the Iterable interface.
It contains only one abstract method. i.e.,
Iterator<T> iterator()
It returns the iterator over the elements of type T.
4.4.2 Iterating ArrayList using Iterator
Let's see an example to traverse ArrayList elements using the Iterator interface.
FileName: ArrayListExample2.java
import java.util.*;
public class ArrayListExample2{
public static void main(String args[]){
ArrayList<String> list=new ArrayList<String>();//Creating arraylist
list.add("Mango");//Adding object in arraylist
list.add("Apple");
list.add("Banana");
list.add("Grapes");
//Traversing list through Iterator
Iterator itr=list.iterator();//getting the Iterator
while(itr.hasNext()){//check if iterator has the elements
System.out.println(itr.next());//printing the element and move to next
}
}
}
188
Lecture No. 29:
4.5 Collection Interface
4.5.1 What is Collection Interface?
The Collection interface is the interface which is implemented by all the classes in the collection
framework. It declares the methods that every collection will have. In other words, we can say that
the Collection interface builds the foundation on which the collection framework depends.
Some of the methods of Collection interface are Boolean add ( Object obj), Boolean addAll (
Collection c), void clear(), etc. which are implemented by all the subclasses of Collection interface.
4.6 List Interface
4.6.1 What is List Interface?
List in Java provides the facility to maintain the ordered collection. It contains the index-based
methods to insert, update, delete and search the elements. It can have the duplicate elements also. We
can also store the null elements in the list.
The List interface is found in the java.util package and inherits the Collection interface. It is a factory
of ListIterator interface. Through the ListIterator, we can iterate the list in forward and backward
directions. The implementation classes of List interface are ArrayList, LinkedList, Stack and Vector.
The ArrayList and LinkedList are widely used in Java programming. The Vector class is deprecated
since Java 5.
4.6.2 List Interface Declaration
public interface List<E> extends Collection<E>
Java List vs ArrayList
/Creating a List of type String using ArrayList
List<String> list=new ArrayList<String>();
189
4.6.3 Java List Example
Let's see a simple example of List where we are using the ArrayList class as the implementation.
import java.util.*;
public class ListExample1{
public static void main(String args[]){
//Creating a List
List<String> list=new ArrayList<String>();
//Adding elements in the List
list.add("Mango");
list.add("Apple");
list.add("Banana");
list.add("Grapes");
//Iterating the List element using for-each loop
for(String fruit:list)
System.out.println(fruit);
}
}
4.7 Array List
4.7.1 What is ArrayList?
Java ArrayList class uses a dynamic array for storing the elements. It is like an array, but there is no
size limit. We can add or remove elements anytime. So, it is much more flexible than the traditional
array. It is found in the java.util package. It is like the Vector in C++.
Figure 2: ArrayList
190
The ArrayList in Java can have the duplicate elements also. It implements the List interface so we
can use all the methods of the List interface here. The ArrayList maintains the insertion order
internally.
It inherits the AbstractList class and implements List interface.
o Java ArrayList class can contain duplicate elements.
o Java ArrayList class maintains insertion order.
o Java ArrayList class is non synchronized.
o Java ArrayList allows random access because the array works on an index basis.
o In ArrayList, manipulation is a little bit slower than the LinkedList in Java because a lot of
shifting needs to occur if any element is removed from the array list.
o We can not create an array list of the primitive types, such as int, float, char, etc. It is required
to use the required wrapper class in such cases. For example:
ArrayList<int> al = ArrayList<int>(); // does not work
ArrayList<Integer> al = new ArrayList<Integer>(); // works fine
Java ArrayList gets initialized by the size. The size is dynamic in the array list, which varies according
to the elements getting added or removed from the list.
4.7.2 Example-ArrayList
FileName: ArrayListExample1.java
import java.util.*;
public class ArrayListExample1{
public static void main(String args[]){
ArrayList<String> list=new ArrayList<String>();//Creating arraylist
list.add("Mango");//Adding object in arraylist
list.add("Apple");
list.add("Banana");
list.add("Grapes");
//Printing the arraylist object
System.out.println(list);
}
}
Output:
[Mango, Apple, Banana, Grapes]
191
4.8 LinkedList
4.8.1 What is LinkedList?
Java LinkedList class uses a doubly linked list to store the elements. It provides a linked-list data
structure. It inherits the AbstractList class and implements List and Deque interfaces.
o Java LinkedList class can contain duplicate elements.
o Java LinkedList class maintains insertion order.
o Java LinkedList class is non synchronized.
o In Java LinkedList class, manipulation is fast because no shifting needs to occur.
o Java LinkedList class can be used as a list, stack or queue.
Figure 3: LinkedList
4.8.2 Example- LinkedList
import java.util.*;
public class TestJavaCollection2{
public static void main(String args[]){
LinkedList<String> al=new LinkedList<String>();
al.add("Ravi");
al.add("Vijay");
al.add("Ravi");
al.add("Ajay");
Iterator<String> itr=al.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
192
}
}
}
Output:
Ravi
Vijay
Ravi
Ajay
4.8.3 ArrayList vs LinkedList
However, there are many differences between the ArrayList and LinkedList classes that are given
below.
Table 1: ArrayList vs LinkedList
ArrayList LinkedList
1) ArrayList internally uses a dynamic array to LinkedList internally uses a doubly linked
store the elements. list to store the elements.
3) An ArrayList class can act as a list only LinkedList class can act as a list and
because it implements List only. queue both because it implements List and
Deque interfaces.
5) The memory location for the elements of an The location for the elements of a linked list
ArrayList is contiguous. is not contagious.
193
6) Generally, when an ArrayList is initialized, a There is no case of default capacity in a
default capacity of 10 is assigned to the LinkedList. In LinkedList, an empty list is
ArrayList. created when a LinkedList is initialized.
o When the rate of addition or removal rate is more than the read scenarios, then go for the
LinkedList. On the other hand, when the frequency of the read scenarios is more than the
addition or removal rate, then ArrayList takes precedence over LinkedList.
o Since the elements of an ArrayList are stored more compact as compared to a LinkedList;
therefore, the ArrayList is more cache-friendly as compared to the LinkedList. Thus, chances
for the cache miss are less in an ArrayList as compared to a LinkedList. Generally, it is
considered that a LinkedList is poor in cache-locality.
o Memory overhead in the LinkedList is more as compared to the ArrayList. It is because, in a
LinkedList, we have two extra links (next and previous) as it is required to store the address
of the previous and the next nodes, and these links consume extra space. Such links are not
present in an ArrayList.
4.9 Vector
4.9.1 What is Vector?
Vector uses a dynamic array to store the data elements. It is similar to ArrayList. However, It is
synchronized and contains many methods that are not the part of Collection framework.
4.9.2 Example-Vector
import java.util.*;
public class TestJavaCollection3{
public static void main(String args[]){
Vector<String> v=new Vector<String>();
v.add("Ayush");
v.add("Amit");
v.add("Ashish");
v.add("Garima");
Iterator<String> itr=v.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
194
}
}
}
Output:
Ayush
Amit
Ashish
Garima
4.9.3 ArrayList vs Vector
Table 2: ArrayList vs Vector
4.10 Stack
4.10.1 What is Stack?
The stack is the subclass of Vector. It implements the last-in-first-out data structure, i.e., Stack. The
stack contains all of the methods of Vector class and also provides its methods like boolean push(),
boolean peek(), boolean push(object o), which defines its properties.
195
4.10.2 Example-Stack
import java.util.*;
public class TestJavaCollection4{
public static void main(String args[]){
Stack<String> stack = new Stack<String>();
stack.push("Ayush");
stack.push("Garvit");
stack.push("Amit");
stack.push("Ashish");
stack.push("Garima");
stack.pop();
Iterator<String> itr=stack.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}
Output:
Ayush
Garvit
Amit
Ashish
4.10.3 Stack Operations
The stack data structure has the two most important operations that are push and pop. The push
operation inserts an element into the stack and pop operation removes an element from the top of the
stack. Imagine it as a stack of plates where you can only add or remove the top plate. Items can be
added (pushed) onto the stack or removed (popped) from it. The most recently added item is the one
that gets removed first. Let's see how push and pop work on stack.
Figure 4: stack
196
Let's push 20, 13, 89, 90, 11, 45, 18, respectively into the stack.
198
Queue provides special methods like:
● offer(E e) – Adds element to the queue
● poll() – Retrieves and removes the head of the queue
● peek() – Retrieves the head without removing it These are safer alternatives to add() and
remove() as they return null instead of throwing exceptions when the queue is empty or full.
199
The Set interface models the mathematical concept of a set — an unordered collection of distinct
elements. It extends the Collection interface, and its behavior is similar to a real-life set where no
two items are the same.
200
🔹 Efficient Search Operations
Since Sets (like HashSet) provide fast contains() methods, they are used where quick lookups are
needed, such as in filters or membership checks.
🔹 Tagging Systems
In systems like blogs, forums, or social media platforms, tags are often stored in Sets to ensure
uniqueness.
🔹 Data Validation
Sets are used to validate whether certain values already exist in a system (e.g., checking if a username
is already taken during signup).
4.13 HASHSET CLASS: INTRODUCTION
4.13.1 What is the HashSet Class?
The HashSet class in Java is a concrete implementation of the Set interface, and it is a part of the
java.util package. It is used to store a collection of unique elements, and it is backed by a
HashMap internally.
HashSet does not allow duplicate elements and does not maintain insertion order. The elements
are stored based on their hash codes, which is why the order of elements appears random and
unpredictable.
Declaration:
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, Serializable
201
✅ Efficient Set Operations
You can perform operations like union, intersection, and difference by using methods like addAll(),
retainAll(), and removeAll().
202
Lecture No : 31
4.14 LINKED HASH SET CLASS: INTRODUCTION
4.14.1 What is the LinkedHashSet Class?
The LinkedHashSet class in Java is a part of the Java Collections Framework, found in the
java.util package. It is a subclass of HashSet and implements the Set interface, just like HashSet,
but with one key difference — it maintains the insertion order of elements.
Internally, LinkedHashSet combines a hash table and a linked list to store elements:
● The hash table ensures that elements are unique and can be accessed quickly.
● The linked list maintains the insertion order of elements.
Declaration:
public class LinkedHashSet<E> extends HashSet<E> implements Set<E>, Cloneable, Serializable
204
✅ Provides Range Views
It offers powerful methods like subSet (), headSet (), and tailSet () to work with specific portions of
the set based on value ranges.
✅ Useful Navigation Methods
It provides methods like first (), last (), comparator (), which allow quick access to boundary elements
or the comparator used for ordering.
205
4.16.2 Why is the TreeSet Used?
The TreeSet is used when you need to store a collection of unique elements in a sorted order, and
also require range queries, floor/ceiling navigation, or reverse views.
✅ Sorted and Unique
Automatically sorts the elements and does not allow duplicates.
✅ Powerful Navigation
Supports methods like lower(), floor(), ceiling(), higher() for navigation based on value.
✅ Range Views
Provides methods like subSet(), headSet(), tailSet() to get portions of the set based on a range of
values.
✅ Efficient Searching
Internally uses a Red-Black Tree to allow logarithmic time complexity for add, remove, and search
operations.
206
Lecture No: 32
4.17 MAP INTERFACE : INTRODUCTION
4.17.1 What is the Map Interface?
The Map interface in Java is a part of the Java Collection Framework, present in the java.util
package. Unlike the other collection types (like List or Set), a Map is not a true collection, but rather
a structure that stores data in the form of key-value pairs.
Each key in a Map must be unique, but values can be duplicated. The key is used to uniquely
identify and retrieve a value.
Declaration:
public interface Map<K, V>
● K stands for the key type
● V stands for the value type
207
🔹 Caching
Maps are used for caching data — storing results of expensive operations with keys so they can be
reused.
🔹 Configuration and Settings
System or application settings (like theme → dark/light, volume → 80%) are often stored in key-
value format.
🔹 Language Translation Tools
Used to map words from one language to another (e.g., English → Hindi)
🔹 Graphs and Trees
Used internally to represent adjacency lists or relationships between nodes.
208
✅ Flexibility
Allows null values and one null key, making it flexible for different use cases.
✅ Memory Efficient
Uses dynamic sizing and internal hashing to manage memory usage effectively.
209
4.19.2 Why is LinkedHashMap Used?
LinkedHashMap is used when you want the advantages of a HashMap (fast access) but also need
to maintain the order of elements.
✅ Maintains Insertion Order
It is useful when you want the entries to be iterated in the same order in which they were added.
✅ Predictable Iteration
Unlike HashMap, you always get a consistent iteration order, which is useful for display, reporting,
or user-facing features.
✅ Fast Performance
Performance is still close to HashMap, with constant time complexity O(1) for put and get
operations.
✅ Custom Ordering
LinkedHashMap can also maintain access order (recently accessed entries first), useful in cache
implementations.
210
4.20 TREE MAP: INTRODUCTION
4.20.1 What is TreeMap?
The TreeMap class in Java is a Map implementation that stores key-value pairs in sorted order
based on the natural ordering of the keys or a custom comparator provided at the time of map
creation.
It is a part of the java. util package and implements the Navigable Map interface, which is a subtype
of SortedMap.
Declaration:
public class TreeMap<K, V> extends AbstractMap<K, V>
implements NavigableMap<K, V>, Cloneable, Serializable
● K – Type of keys
● V – Type of values
Internally, TreeMap uses a Red-Black Tree (a type of self-balancing binary search tree) to store
data, ensuring that the keys are always sorted.
211
🔹 Navigable Applications
Useful in applications like calendar systems, timelines, or schedulers, where you often need to find
the next or previous event.
🔹 Range Queries
Efficient for retrieving a submap between certain keys — useful in stock trading apps, time-series
analysis, etc.
212
Lecture No.:33
4.21 HashTable Class in Java
4.21.1 What is HashTable?
The Hashtable class in Java is part of the Java Collection Framework and is used to store key-
value pairs. It's similar to a dictionary or map.
● It is found in the java.util package.
● It implements the Map interface.
● Keys and values cannot be null.
● It is synchronized (thread-safe), which means it is safe to use in multi-threaded
environments.
Table 3 : Hash Table Feature
Feature Description
Type Map (key-value pairs)
Thread
Yes (synchronized)
Safety
Not allowed (neither key nor value can be
Null Values
null)
Ordering No guarantee of order
Performanc Slower than HashMap due to
e synchronization
Basic Syntax
import java.util.Hashtable;
public class Example {
public static void main(String[] args) {
Hashtable<Integer, String> table = new Hashtable<>();
// Adding elements
table.put(1, "Apple");
table.put(2, "Banana");
table.put(3, "Cherry");
// Accessing elements
213
System.out.println(table.get(2)); // Output: Banana
2. Key-Value Storage
214
You can store and retrieve values using unique keys, which is useful when you need fast lookups
(like a dictionary).
Example:
Hashtable<String, String> countryCodes = new Hashtable<>();
countryCodes.put("IN", "India");
countryCodes.put("US", "United States");
System.out.println(countryCodes.get("IN")); // Output: India
4. Automatic Synchronization
You don’t need to manually synchronize access to the map (unlike HashMap +
Collections.synchronizedMap()).
But why not always use it?
If thread safety isn’t needed, use HashMap—it's faster.
If you need concurrent but high-performance access, use ConcurrentHashMap.
4.21.3 Where to Use HashTable?
Here are some scenarios:-
1. Storing and Retrieving User Credentials
Use case: Login systems
Keys: Usernames or emails
Values: Passwords (hashed) or user details
Example:-
Hashtable<String, String> users = new Hashtable<>();
users.put("john_doe", "hashed_password_123");
215
HashMap<String, Integer> cart = new HashMap<>();
cart.put("apple", 3);
cart.put("milk", 1);
3. Counting Frequencies (Word Count, Char Count)
Use case: Analytics, Search Engine
Keys: Words/Characters
Values: Count of occurrences
Example:-
HashMap<String, Integer> wordCount = new HashMap<>();
wordCount.put("hello", wordCount.getOrDefault("hello", 0) + 1);
216
for (int num : arr) {
if (set.contains(num)) {
System.out.println("Duplicate found: " + num);
}
set.add(num);
}
218
Lecture No.34
4.23 Comparable Interface
4.23.1 What is Comparable Interface in Java?
The Comparable interface is used to define the natural ordering of objects.
It allows you to compare two objects of the same class, so they can be sorted automatically (e.g.,
using Collections.sort() or Arrays.sort()).
Key Method of Comparable:
Example:-
public int compareTo(T o);
● Returns:
o 0 → if objects are equal
o < 0 → if current object is less than o
o > 0 → if current object is greater than o
219
this.name = name;
this.marks = marks;
}
@Override
public int compareTo(Student other) {
return this.marks - other.marks; // ascending order
}
}
// Usage
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("Alice", 45));
list.add(new Student("Bob", 45));
list.add(new Student("Charlie", 90));
220
Key Method of Comparator:
221
}
}
Usage:
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("Charlie", 90));
list.add(new Student("Alice", 45));
list.add(new Student("Bob", 45));
Use for Multiple Fields ❌ Not directly ✅ Yes, multiple comparisons allowed
Modifies class? Yes No
222
A class in Java is a blueprint for creating objects. It defines the data (attributes) and behavior
(methods) that the objects created from it will have.
Key Properties of a Java Class
1.Fields / Variables
These are the attributes or properties of a class. They hold the data.
class Car {
String color;
int speed;
}
📝 Here, color and speed are fields of the Car class.
2.Methods
These define the behaviors or actions the class can perform.
java
CopyEdit
void startEngine() {
System.out.println("Engine started");
}
📝 Methods describe what an object can do.
3. Constructors
Special methods used to create and initialize objects of the class.
Car(String c, int s) {
color = c;
speed = s;
}
🧠 Called automatically when an object is created.
4. Access Modifiers
They define the visibility of class members.
● public: Accessible everywhere
● private: Accessible only inside the class
● protected: Accessible in the same package or subclass
● default (no modifier): Package-private
223
private String engineType;
public int wheels;
5. Encapsulation
The class hides internal details using private variables and provides access through getters/setters.
private String model;
public String getModel() {
return model;
}
public void setModel(String m) {
model = m;
}
6. Static Members
Belong to the class itself rather than objects. Shared by all instances.
static int numberOfCars;
7. Inheritance (Optional)
A class can inherit properties and behaviors from another class using the extends keyword.
class ElectricCar extends Car {
int batteryCapacity;
}
8. Polymorphism
Allows one method to have many forms (method overloading or overriding).
void drive() { }
void drive(int speed) { } // Method overloading
224
🔟 Object Creation
Classes are used to create objects (instances) that represent real-world entities.
Example:-
Car myCar = new Car("Red", 120);
Table 7: Summarize
Property Description
Fields Variables to store data
Methods Define actions/behaviors
Constructors Initialize objects
Access Modifiers Control visibility
Encapsulation Hiding data using private + getters/setters
Static Members Shared class-level variables/methods
Inheritance Inherit from parent class
Polymorphism One method, many forms
Abstraction Hiding complex logic, showing essential info
Object Creation Using new keyword to instantiate class
225
Questions
1. Mention some of the best practices while using Java Collections.
2. Describe the hierarchy of the Collection Framework in Java.
3. Differentiate between Array and collection.
4. How do you reverse an ArrayList?
5. Name the differences between collection and Collections.
6. Differentiate between concurrent collection and synchronized collection.
7. List the differences between Array and ArrayList.
8. How do you reverse an ArrayList?
9. Explain the differences between Iterator and ListIterator.
10. What is the default size of the load factor in a hashing based collection?
11. Differentiate between iterator and enumeration.
12. How do you make an ArrayList read-only in Java?
13. What are the methods that Java queue interface provide?
14. Name the differences between ArrayList and Vector.
15. What are the differences between ArrayList and LinkedList?
16. Differentiate between set and map.
17. How do you sort an ArrayList in descending order?
18. What are the differences between HashSet and TreeSet.
19. List the differences between comparable and comparator.
20. Name the differences between queue and stack.
21. Differentiate between FailFast and FailSafe.
22. How do you synchronise List, Set and Map elements?
23. What are the methods that Java Stack class provide?
24. What are the uses of Properties class and the advantages of Properties file?
25. Explain the differences between remove() and poll() method of queue interface.
26. What is Equals() method? Explain with an example.
27. What are the differences between the respective remove() methods of Iterator and collection?
28. How do you handle Hash-Collision in HashTable in Java?
29. Tell me the differences between a list and a set.
30. How do you convert an ArrayList to an Array and vice versa?
31. Why does not the Collection Interface extend Serializable and Cloneable Interfaces?
32. How do you reverse an ArrayList?
226
33. Differentiate between HashMap and Hashtable.
34. How do you synchronise an ArrayList?
35. What is the priority queue?
36. How do you implement HashSet in Java and how does it use hashing?
37. What is the list interface's use in Java?
38. Explain the differences between HashMap and TreeMap.
39. HashTable does not allow null, whereas HashMap does. Why is it so?
40. How do you use a custom object as a key in map, set or other collection classes?
41. What is HashCode() method?
42. Is there any need for synchronised ArrayList when we have synchronised Vectors in Java?
43. What is the dictionary class?
44. Why does not the Collection Interface extend the Map interface or vice-versa?
45. What is CopyOnWriteArrayList?
46. How many types of LinkedList does Java support? What are they?
47. What is Hash-Collision in HashTable?
48. Differentiate between Array length and ArrayList size.
49. What is a blocking queue?
50. How do you sort the collection objects in Java?
51. What is NavigableMap? How is it different from Map?
52. Why does ConcurrentModificationException occur on iteration in Java?
53. What is the purpose of the RandomAccess interface and where is it implemented?
54. How do you use ConcurrentHashMap?
227
Unit-5 Spring Framework
Lecture No. Topic Description
228
Lecture No.:35
5.1 Spring Framework: INTRODUCTION
5.1.1 What is Spring Framework?
Spring Framework is a Java platform that provides comprehensive infrastructure support for
developing Java applications. Spring handles the infrastructure so you can focus on your application.
Spring enables you to build applications from “plain old Java objects” (POJOs) and to apply enterprise
services non-invasively to POJOs. This capability applies to the Java SE programming model and to
full and partial Java EE.
Examples of how you, as an application developer, can use the Spring platform advantage:
● Make a Java method executes in a database transaction without having to deal with transaction
APIs.
● Make a local Java method a remote procedure without having to deal with remote APIs.
● Make a local Java method a management operation without having to deal with JMX APIs.
● Make a local Java method a message handler without having to deal with JMS APIs.
230
Lecture-36
5.2 Spring Inversion of Control
5.2.1 What is Spring Inversion of Control
Inversion of Control is a principle in software engineering which transfers the control of objects or
portions of a program to a container or framework. We most often use it in the context of object-
oriented programming. Spring IoC (Inversion of Control) Container is the core of Spring Framework.
It creates the objects, configures and assembles their dependencies, manages their entire life cycle.
The Container uses Dependency Injection (DI) to manage the components that make up the
application. It gets the information about the objects from a configuration file (XML) or Java Code
or Java Annotations and Java POJO class. These objects are called Beans. Since the Controlling of
Java objects and their lifecycle is not done by the developers, hence the name Inversion of Control.
The followings are some of the main features of Spring IoC,
• Creating Object for us,
• Managing our objects,
• Helping our application to be configurable,
• Managing dependencies
5.2.2 Why use Spring Inversion of Control
1. Loose Coupling
● Objects don't create their own dependencies (they're provided/injected)
● Components depend on interfaces rather than concrete implementations
● Makes code more modular and flexible for changes
2. Improved Testability
● Easier to mock dependencies during unit testing
● Enables isolated testing of components
● Simplifies integration testing with different configurations
3. Simplified Object Management
● Spring handles object lifecycle (creation, initialization, destruction)
● No need for manual singleton management
● Reduces boilerplate factory/registry code
4. Centralized Configuration
● Dependency relationships defined in one place (XML, JavaConfig, or annotations)
● Easy to modify application structure without changing code
● Supports different configurations for different environments
231
5. Promotes Good Design Practices
● Encourages programming to interfaces
● Follows Single Responsibility Principle (SRP)
● Makes Dependency Injection pattern natural to implement
6. Flexible Dependency Resolution
● Constructor injection (recommended for mandatory dependencies)
● Setter injection (for optional dependencies)
● Field injection (through @Autowired)
● Method injection for special cases
7. Supports Multiple Scopes
● Singleton (default) - one instance per container
● Prototype - new instance each time
● Web-aware scopes (request, session, application)
● Custom scopes can be defined
8. Lifecycle Management
● Callback methods (@PostConstruct, @PreDestroy)
● Awareness interfaces (ApplicationContextAware, BeanNameAware)
● Ordered initialization of dependent beans
9. Integration with Other Spring Features
● Foundation for Spring AOP (proxying)
● Works seamlessly with transaction management
● Enables Spring's declarative services (@Transactional, @Cacheable)
Without IoC:
public class OrderService {
private OrderRepository repository = new JdbcOrderRepository(); // Tight coupling
// ...
}
With Spring IoC:
@Service
public class OrderService {
private final OrderRepository repository;
233
Figure - 2 Aspect-oriented programming
• AspectJ: It is an extension for Java programming created at PARC research centre. It uses Java like
syntax and included IDE integrations for displaying crosscutting structure. It has its own compiler
and weaver, on using it enables the use of full AspectJ language.
• JBoss: It is an open-source Java application server developed by JBoss, used for Java development.
• Spring: It uses XML based configuration for implementing AOP, also it uses annotations which are
interpreted by using a library supplied by AspectJ for parsing and matching. Currently, AspectJ
libraries with Spring framework are dominant in the market, therefore let’s have an understanding of
how Aspect-oriented programming works with Spring.
5.3.2 Why use AOP
1. Separation of Cross-Cutting Concerns
● Isolates system-wide concerns (logging, security, transactions) from business logic
● Prevents "code tangling" where multiple concerns are mixed in single modules
● Eliminates "code scattering" where similar code appears across many methods
2. Cleaner Business Logic
● Core business code focuses purely on business functionality
● Removes infrastructure-related code from business methods
● Makes business components more readable and maintainable
3. Declarative Programming Model
● Add behavior to existing code without modifying the code itself
● Configure aspects through annotations or XML
● Example: Add transaction support with just @Transaction
234
5.3.3 Where to Use AOP
1. Enterprise Web Applications
● Large-scale business applications (ERP, CRM systems)
● E-commerce platforms
● Banking and financial systems
● Government applications
● Healthcare systems
2. RESTful Web Services & Microservices
● Building REST APIs with Spring MVC or Spring WebFlux
● Microservices architecture with Spring Boot + Spring Cloud
● Backend for mobile applications
● Integration between different systems
5.4 Bean Scopes- Singleton
5.4.1 What are Bean Scopes- Singleton
Bean Scope in Spring defines:
● How many objects of a bean Spring will create.
● How long that object will exist (its lifetime).
@Autowired
private Student s1;
@Autowired
private Student s2;
@GetMapping("/check")
public String checkBean() {
235
return "HashCode of s1: " + s1.hashCode() +
" , HashCode of s2: " + s2.hashCode();
}
}
5.4.2 Why use Bean Scopes- Singleton
Use Singleton when:
● Bean has no user-specific data.
● Same behavior for all users/requests.
● Bean holds common business logic.
@Service
public class StudentService {
public String showData() {
return "This is Student Service";
}
}
5.4.3 Where to Use Bean Scopes- Singleton
● No Instance Variables for user data
● No Sensitive/Confidential Data
● Only Logic / Utility Methods
● Resource-Intensive Beans (like DB Connection Pools)
● Common Service shared across users
236
Lecture-37
5.5 Prototype
5.5.1 What is Prototype
Prototype Scope = New Object Every Time you request the Bean from Spring Container.
Syntax
@Component
@Scope("prototype")
public class Student {
public Student() {
System.out.println("Student Object Created");
}
}
Example
@RestController
public class MyController {
@Autowired
private Student s1;
@Autowired
private Student s2;
@GetMapping("/check")
public String checkBean() {
return "HashCode of s1: " + s1.hashCode() +
" , HashCode of s2: " + s2.hashCode();
}
}
5.5.2 Why use Prototype
● Identify Problems Early:
Prototyping helps uncover potential usability issues, design flaws, and functional problems before
significant resources are invested in development.
● Test Feasibility:
237
Prototypes allow designers and developers to test the feasibility of their ideas and ensure that the
product concept is viable.
● User Testing:
Prototypes can be used to gather user feedback and insights, ensuring that the final product meets user
needs and expectations.
5.5.3 Where to Use Prototype
● Testing Phase:
Prototypes are crucial in the final testing phase of a design thinking process to determine how
users interact with a product, identify potential issues, and assess the success of implemented
solutions.
● User Feedback:
Prototypes allow designers to gather user feedback early in the development process, enabling
them to make informed decisions and refine their designs.
● Iterative Design:
Prototyping facilitates rapid iteration, allowing designers to quickly make changes and
improvements based on user feedback and testing results.
2. Specific Fields and Applications:
● Semantics:
Prototypes can be used to explore and test different semantic models or representations.
● Electronics:
Prototypes are used to test and refine electronic circuits, devices, and systems before mass
production.
● Software Programming:
In software development, prototypes are used to test algorithms, user interfaces, and system
architectures.
● Product Development:
Prototypes are used to test and refine products before they are put into mass production.
● Architectural Design:
Architects use prototypes (models) to visualize and test the design of buildings and structures.
● Web Development:
Prototypes are used to test and refine web pages and websites before they are put into production.
● Mobile App Development:
Prototypes are used to test and refine mobile apps before they are put into production.
238
5.6 Request
5.6.1 What is Request
A Request object consists of:
● the name of the operation to be invoked
● an NVList containing arguments for the operation.
Each item in the list is a NamedValue object, which has three parts:
1. the name of the argument
2. the value of the argument (as an Any object)
3. the argument mode flag indicating whether the argument is for input, output, or both
Request objects may also contain additional information, depending on how an operation was defined
in the original IDL interface definition. For example, where appropriate, they may contain
a NamedValue object to hold the return value or exception, a context, a list of possible exceptions,
and a list of context strings that need to be resolved.
5.6.2 Why use Request
Using "request" in the context of web development (especially with HTTP) refers to the information
a client (like a browser) sends to a server to initiate a specific action or request data. It's a fundamental
part of how web applications communicate, and the "request" object contains details about the
request, including the method (GET, POST, etc.), URL, headers, and data.
5.6.3 Where to Use Request
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
String username = request.getParameter("username");
response.getWriter().println("Hello " + username);
}
HttpServletRequest → Reads data from client (like form data, URL parameters).
5.7 Session
5.7.1 What is Session?
n simple words → Session means storing user information temporarily so that it can be used across
multiple pages or requests until the user logs out or the session expires.
TTP protocol is stateless → every request from a browser to a server is independent → server
doesn't remember you.
239
→ To solve this → Session is used to store user-specific data like:
● Login information
● Cart data (in shopping websites)
● Preferences
● Temporary Data
5.7.2 Why use Session
HTTP = Stateless Protocol
→ Every request is fresh & independent.
Example without Session:
pgsql
session.invalidate();
5.8 Application
5.8.1 What is Application?
In application scope, the container creates one instance per web application runtime. It is almost
similar to singleton scope with only two differences i.e. 1. The application scoped bean is singleton
per ServletContext, whereas singleton scoped bean is singleton per ApplicationContext. Please note
that there can be multiple application contexts within a single application. 2. The application scoped
bean is visible as a ServletContext attribute
5.8.2 Why use Application?
→ Session is for one user only
→ Request is for one request only
But sometimes → You need to store → Global Data for All Users
// Getting Application Object
240
ServletContext context = getServletContext();
// Store data in Application scope
context.setAttribute("websiteName", "Nishant Web App");
// Retrieve data in any Servlet
String name = (String) context.getAttribute("websiteName");
5.8.3 Where to Use Application?
Application (ServletContext) is used → When you want to store → Common Data → Accessible
to All Users of your Website/Application.
5.9 Web Socket
5.9.1 What is Web Socket
The WebSocket Protocol enables two-way communication between a client and a remote host that
has opted-in to communicate with the client. WebSocket Protocol provides a single TCP connection
for traffic in both directions. This is especially useful for multi-user applications with simultaneous
editing and multi-user games. In this type of web application, HTTP is used only for the initial
handshake. The server can respond with HTTP status 101 (switching protocols) if it agrees – to the
handshake request. If the handshake succeeds, the TCP socket remains open, and both the client and
server can use it to send messages to each other. When first accessed, WebSocket scoped beans are
stored in the WebSocket session attributes. The same bean instance is then returned during the entire
WebSocket session. Please note that websocket scoped beans are typically singleton and live longer
than any individual WebSocket session.
5.9.2 Why use Web Socket
WebSocket = A communication protocol for Real-Time, Bi-Directional (Two-Way) communication
between Client (Browser) and Server over a single connection.
HTTP = Request-Response Protocol
Client has to request → Server responds
No Real-Time Push from Server
Every time client wants data → Client must send request → Server replies
5.9.3 Where to Web Socket
Real-Time Updates
Instant Notification
Live Chatting
Push Data from Server without Request
Two-Way Communication (Full Duplex)
241
Lecture-38
5.10 Autowiring ,Annotation
5.10.1 What is Auto wiring, Annotations
Autowiring in the Spring framework can inject dependencies automatically. The Spring container
detects those dependencies specified in the configuration file and the relationship between the beans.
This is referred to as Autowiring in Spring. To enable Autowiring in the Spring application we should
use @Autowired annotation. Autowiring in Spring internally uses constructor injection. An autowired
application requires fewer lines of code comparatively but at the same time, it provides very little
flexibility to the programmer. Modes of Autowiring Modes Description No This mode tells the
framework that auto wiring is not supposed to be done. It is the default mode used by Spring. byName
It uses the name of the bean for injecting dependencies. byType It injects the dependency according
to the type of bean. Constructor It injects the required dependencies by invoking the constructor.
Autodetect The autodetect mode uses two other.
5.10.2 Why use Auto wiring, Annotations
Autowiring in Spring is a feature that automatically injects the dependent beans (objects) into a class
without using explicit <bean> configurations in XML.
Reduces Configuration No need to manually declare dependencies in XML for every bean.
Loose Coupling Spring automatically handles object creation and dependency injection.
This could be used for assigning primary key values to persistent objects. This is equivalent
to the XML element tag pre-persist.
▪ PostPersist: Methods marked with this annotation will be invoked after an object has
transitioned to the persistent state. You might want to use such methods to update a screen
after a new row is added. This is equivalent to the XML element tag post-persist.
▪ PostLoad: Methods marked with this annotation will be invoked after all eagerly fetched
fields of your class have been loaded from the datastore. No other persistent fields can be
accessed in this method. This is equivalent to the XML element tag post-load
5.11.2 Why use Life Cycle Call backs
● Resource Management:
When a component or application is no longer in use (e.g., an activity is paused or stopped), lifecycle
callbacks help you release resources (like memory, network connections, or database connections) to
prevent performance issues and crashes.
● State Management:
Lifecycle callbacks enable you to save and restore the state of a component or application, ensuring
that the user experience is consistent even when the application is temporarily paused or killed by
the system.
● Event Handling:
Lifecycle callbacks allow you to respond to specific events or changes in the application's lifecycle,
such as when a component is created, destroyed, or becomes visible or invisible to the user.
● Example in Android:
In Android, lifecycle callbacks like onCreate(), onStart(), onResume(), onPause(), onStop(),
and onDestroy() are used to manage the lifecycle of activities and fragments.
● Example in Web Development:
In web development frameworks like Angular, lifecycle hooks
like ngOnInit(), ngOnChanges(), ngDoCheck(), and ngOnDestroy() are used to manage the lifecycle
of components.
243
5.11.3 Where to use Life Cycle Call backs
● Rails Active Record: Callbacks allow you to trigger logic before or after an Active Record
object is initialized, created, saved, updated, deleted, validated, or loaded from the database.
● Spring Beans: Lifecycle callbacks can be used to perform initialization tasks
(@PostConstruct) or cleanup tasks (@PreDestroy) on Spring beans.
● JPA: JPA provides callback methods for monitoring changes in the lifecycle of persistent
objects.
● How:You define callback methods within your model or bean class, and the framework
automatically calls them at the appropriate stages.
2. UI/Component Lifecycle (e.g., in Android, React, or Stimulus):
● Purpose:
To manage the state and behavior of UI elements or components as they are created, rendered,
updated, or destroyed.
5.12 Bean Configuration styles
5.12.1 What is Bean Configuration styles
The central artifacts in Spring’s Java configuration support are @Configuration-annotated classes
and @Bean-annotated methods.
The @Bean annotation is used to indicate that a method instantiates, configures, and initializes a new
object to be managed by the Spring IoC container. For those familiar with Spring’s <beans/> XML
configuration, the @Bean annotation plays the same role as the <bean/> element. You can
use @Bean-annotated methods with any Spring @Component. However, they are most often used
with @Configuration beans.
Annotating a class with @Configuration indicates that its primary purpose is as a source of bean
definitions. Furthermore, @Configuration classes let inter-bean dependencies be defined by calling
other @Bean methods in the
@Configuration
public class AppConfig {
@Bean
public MyServiceImpl myService() {
return new MyServiceImpl();
}
}
The preceding AppConfig class is equivalent to the following Spring <beans/> XML:
244
<beans>
<bean id="myService" class="com.acme.services.MyServiceImpl"/>
</beans>
5.12.2 Why use Bean Configuration styles
● ependency Injection:
Bean configuration styles, particularly with @Bean and @Autowired, allow for dependency
injection, where dependencies are passed to a class rather than the class creating them itself. This
promotes loose coupling and makes code easier to test and maintain.
● Modularity and Organization:
@Configuration classes act as factories for creating and configuring beans, promoting modularity and
making it easier to organize and manage application components.
● Testability:
Dependency injection and the use of @Bean methods make it easier to test individual components in
isolation, as dependencies can be mocked or replaced during testing.
● Centralized Configuration:
Using @Configuration classes allows for centralized configuration of beans, making it easier to
manage and modify application settings.
● Lifecycle Management:
Spring manages the lifecycle of beans, including creation, initialization, and destruction, simplifying
the developer's workload.
● Inter-Bean Dependencies:
@Bean methods within @Configuration classes can define inter-bean dependencies, allowing for
complex relationships between components.
● Third-Party Class Integration:
@Bean is used to integrate third-party classes or jars into the Spring application context.
● Annotation-Based Configuration:
Annotation-based configuration, using annotations like @Component, @Service, @Repository,
and @Autowired, simplifies the configuration process and reduces boilerplate code.
● Spring IoC Container:
Bean configuration styles are used to define beans that are managed by the Spring Inversion of
Control (IoC) container, which is responsible for creating, configuring, and managing the
application's components.
5.12.3 Where to use Bean Configuration styles
1. XML Configuration:
245
● Where: Primarily used in older Spring projects or when needing a more declarative approach
to bean configuration.
● How: Define beans and their dependencies within an XML file (e.g., applicationContext.xml)
using <bean> tags, specifying properties, dependencies, and scopes.
246
Lecture-39
5.13 Spring Boot build System
5.13.1 What is Spring Boot build System?
Spring Boot team provides a list of dependencies to support the Spring Boot version for its every
release. You do not need to provide a version for dependencies in the build configuration file. Spring
Boot automatically configures the dependencies version based on the release.
5.13.2 Why use Spring boot build system?
. Spring Boot helps you to create stand-alone, production-grade Spring-based applications that you
can run. We take an opinionated view of the Spring platform and third-party libraries, so that you can
get started with minimum fuss. Most Spring Boot applications need very little Spring configuration.
5.13.3 Where to Use Spring boot build system?
Spring Boot is particularly useful for a microservice approach to software development architecture.
Microservices are a popular way to build small, autonomous teams that can work independently—
and by their very nature—microservices only work in the backend.
247
Lecture-40
5.14 Spring Boot code structure
5.14.1 What is Spring Boot code structure?
A typical Spring Boot project structure follows a convention-over-configuration approach, organizing
code into src/main/java for source code, src/main/resources for configuration and static files,
and src/test for tests.
Here's a breakdown of the key directories and their purposes:
Core Directories:
● src/main/java:
● Contains the main application code, typically organized into packages.
● You'll find your controllers, services, repositories, models, and configuration classes here.
● The root package (e.g., com.example.myapp) should be named according to your organization's domain.
src/main/resources:
● Holds configuration files (e.g., application.properties, application.yml) and static resources (CSS,
JavaScript, images).
● You can also store templates (e.g., for Thymeleaf) in this directory.
src/test/java:
● Contains the test classes for your application, organized similarly to the main code.
src/test/resources:
● Holds resources needed for tests, such as test configuration files.
target:
● This directory is generated by the build tool (Maven or Gradle) and contains compiled class files and other
build artifacts.
5.14.2 Why use Spring Boot code structure?
A good Spring Boot code structure promotes clarity, organization, modularity, and scalability,
making it easier to manage, collaborate on, and maintain applications, even as they grow in
complexity. It also facilitates efficient build and deployment processes.
Here's a breakdown of why a well-structured Spring Boot application is beneficial:
1. Clarity and Organization:
● A structured approach helps developers quickly understand the different components and their
relationships within the application.
● This makes it easier to find specific code sections or classes, reducing the time spent searching and
improving overall development efficiency.
248
2. Modularity:
● Spring Boot encourages a modular approach, where the application is divided into logical components
like controllers, services, repositories, and configurations.
● This modularity allows developers to focus on specific parts of the application without worrying about
unrelated code, promoting independent development and testing.
249
Lecture -41
5.15 Boot Runner and Logger
5.15.1 What is Spring Boot Runner and Logger?
In Spring Boot, a logger is an object used to generate log messages, aiding in application debugging,
monitoring, and troubleshooting by recording events and information during runtime. Spring Boot
uses the SLF4J (Simple Logging Facade for Java) interface as the primary abstraction for creating
log messages.
5.15.2 Why use Spring Boot Runner and Logger?
In Spring Boot, loggers are crucial for monitoring application behavior, debugging issues, and
ensuring application health by providing insights into runtime events and errors. They allow
developers to track the flow of the application, monitor issues, and debug efficiently.
By incorporating runners into your Spring Boot applications, you can streamline initialization tasks,
enhance application reliability, and elevate overall development efficiency.
5.15.3 Where to use Spring Boot Runner and Logger?
Logging in Spring Boot plays a vital role in Spring Boot applications for recording information,
actions, and events within the app. It is also used for monitoring the performance of an application,
understanding the behavior of the application, and recognizing the issues within the application
By incorporating runners into your Spring Boot applications, you can streamline initialization tasks,
enhance application reliability, and elevate overall development efficiency.
5.16 building restful web services
5.16.1 What is building restful web services?
Building Restful web services involves designing and implementing services that adhere to the
principles of Representational State Transfer (REST), a style of software architecture for distributed
systems, typically using HTTP for communication. These services are designed to be stateless,
scalable, and easy to maintain.
5.16.2 Why use building restful web services?
Building Restful web services offers benefits like simplicity, scalability, and platform independence,
making them ideal for modern web applications and APIs. They leverage standard HTTP methods,
are easy to design and implement, and support various data formats, enhancing flexibility and
efficiency.
250
Here's a more detailed explanation of the advantages:
● Simplicity and Ease of Use:
RESTful APIs use standard HTTP methods (GET, POST, PUT, DELETE) for data manipulation,
making them easy to understand and implement.
● Scalability:
REST's stateless nature and client-server architecture allow for horizontal scaling, where multiple
servers can handle requests in parallel, ensuring high performance under heavy loads.
● Platform Independence:
REST APIs are not tied to any specific programming language or platform, allowing developers to
use any technology to build clients and servers.
● Flexibility:
REST supports various data formats (JSON, XML, etc.), enabling developers to choose the most
suitable format for their needs.
● Loose Coupling:
RESTful services are designed to be loosely coupled, meaning the client and server can evolve
independently without affecting each other.
● Caching:
REST APIs support caching, allowing clients to store data locally and reduce the load on the server.
● Security:
REST APIs can be secured using various methods, including authentication and encryption, to protect
sensitive data.
5.16.3 Where use building restful web services?
● APIs for Mobile and Web Applications: RESTful APIs are a common choice for building APIs that
allow mobile and web applications to access and manipulate data on remote systems.
● Microservices: RESTful APIs are a key component in building microservices architectures, where
applica5.16.3tions are broken down into small, independent services that communicate via APIs.
● Cloud Computing: RESTful APIs are well-suited for cloud environments, allowing applications to
interact with cloud services and resources.
● Data Exchange: RESTful services are used for exchanging data between different systems or
applications, enabling interoperability and integration.
● Web Services: RESTful services are often used to expose functionalities as web services, allowing
applications to interact with each other over the interne
251
5.17 Rest Controller
5.17.1What is Rest Controller?
In Spring Boot, @RestController is a specialized version of @Controller used for building RESTful
web services, combining the functionalities of @Controller and @ResponseBody to simplify the
creation of controllers that return data directly to the client, typically in JSON or XML format.
5.17.2 Why use Rest Controller?
The @RestController annotation in Spring Boot is a specialized version of the @Controller
annotation. It is designed for building RESTful web services and simplifies the development process
by combining the functionality of @Controller and @ResponseBody
5.17.3 Where to use Rest Controller?
Spring RestController annotation is used to create RESTful web services using Spring MVC. Spring
RestController takes care of mapping request data to the defined request handler method. Once
response body is generated from the handler method, it converts it to JSON or XML response.
252
Lecture-42
5.18 Request Mapping and Request BodyQ
5.18.1What is Request Mapping and Request Body?
By using @RequestBody annotation you will get your values mapped with the model you created in
your system for handling any specific call. While by using @ResponseBody you can send anything
back to the place from where the request was generated. Both things will be mapped easily without
writing any custom parser etc.
5.18.2 Why use Request Mapping and Request Body?
The @RequestBody annotation in Spring Boot is used to bind the body of an HTTP request to a
method parameter in a controller handler method.
The @RequestMapping annotation is used to map requests to controllers methods. It has various
attributes to match by URL, HTTP method, request parameters, headers, and media types. You can
use it at the class level to express shared mappings or at the method level to narrow down to a specific
endpoint mapping.
5.18.3 Where to use Request Mapping and Request Body?
The @RequestMapping annotation is used to map requests to controllers methods. It has various
attributes to match by URL, HTTP method, request parameters, headers, and media types. You can
use it at the class level to express shared mappings or at the method level to narrow down to a specific
endpoint mapping.
253
Lecture-43
5.19 path variable and request parameter
5.19.1 What is path variable and request parameter?
URL: `api/users/{id}` `{id}` is a path variable used to specify a particular user. 𝗥𝗲𝗾𝘂𝗲𝘀𝘁
𝗣𝗮𝗿𝗮𝗺𝗲𝘁𝗲𝗿𝘀 Request parameters are used to filter, sort, or provide more context to the specified
resources. They are added to the end of a URL after a '?' symbol.
5.19.2 Why use path variable and request parameter ?
Use @RequestParam for accessing query parameters when the parameters are optional or when
dealing with a large number of parameters. Use @PathVariable when the parameters are mandatory
and part of the URL path, especially in RESTful APIs where the URL structure reflects the resource
hierarchy.
5.19.3 Where to use path variable and request parameter?
when dealing with a single, specific item, like the unique silver ball, use a path variable. When
filtering by attributes like color, use a query parameter.
5.20 GET,POST,PUT ,DELETE API
5.20.1 What is GET,POST,PUT ,DELETE API?
● GET:
Retrieves data from a specified resource. It's used to request information from a server.
● POST:
Creates a new resource on the server. It's used to send data to the server to create a new entry.
● PUT:
Updates an entire resource on the server. It replaces the existing resource with the data sent in the
request.
● DELETE:
254
● DELETE: Used to remove a resource from the server. It is idempotent (repeating the request has
the same effect), not cacheable, and typically returns an acknowledgment.
5.20.3 Where to use GET,POST,PUT ,DELETE API?
To understand HTTP methods—GET, POST, PUT, and DELETE—used in Restful APIs,
5.21 build web applications
5.21.1 What is build web applications?
Building web applications with APIs (Application Programming Interfaces) involves using APIs to
enable communication and data exchange between the web application's front-end (user interface)
and back-end (server-side logic). APIs act as a bridge, allowing the application to interact with
external services and data sources, enhancing functionality and user experience.
5.21.2Why use to build web applications ?
APIs are crucial for building web applications because they enable seamless communication and data
exchange between different systems, allowing developers to leverage existing functionalities,
integrate with external services, and create more flexible and scalable applications.
Here's a more detailed explanation:
● Interoperability and Integration:
APIs facilitate communication between different software systems, regardless of their programming
language or platform, enhancing interoperability and allowing for the exchange of data and
functionality.
● Data Access and Sharing:
APIs allow web applications to access and consume data and services from various sources, enabling
developers to build applications with richer features and functionalities without having to build
everything from scratch.
● Reduced Development Time:
By providing pre-built, ready-to-use code, APIs can significantly reduce development time, allowing
developers to focus on building unique features and functionality for their web applications.
● Enhanced User Experience:
APIs can be used to integrate with external services like social media platforms, payment gateways,
and mapping services, enhancing the user experience and offering additional features.
● Scalability and Flexibility:
API-driven development enables the creation of more scalable and flexible applications, as different
services can be developed and deployed independently, allowing for easier maintenance and updates.
● Microservices Architecture:
255
APIs play a crucial role in microservices architecture, enabling different services to communicate
with each other to perform specific tasks.
● Mobile Application Integration:
Mobile applications frequently use APIs to interact with a web application's backend and retrieve data
or perform actions on behalf of the user.
● Automation:
APIs can automate processes and perform actions programmatically, such as sending notifications or
updating data.
● Business Growth:
APIs can promote business growth by enabling third-party developers to create applications that
enhance your offerings.
5.21.3 Where to use web applications?
To build web applications using APIs, you can leverage various technologies and frameworks,
including ASP.NET Web API (for .NET), Flask and Django (for Python), Express.js (for Node.js),
and Spring Boot (for Java), each offering different strengths and features.
Here's a more detailed breakdown:
Frameworks and Technologies:
● ASP.NET Web API (for .NET):
A powerful framework for building RESTful web services and APIs, ideal for .NET
developers. Microsoft Learn provides comprehensive documentation and tutorials.
● Flask (for Python):
A lightweight and flexible microframework for building web applications and APIs, known for its
simplicity and ease of use. Twilio provides a tutorial on creating APIs with Python and Flask.
● Django (for Python):
A high-level Python web framework that includes a built-in REST framework, making it a robust
choice for building APIs and web applications. web-design-eastbourne.co.uk discusses Django's
REST framework.
● Express.js (for Node.js):
A fast and flexible Node.js web application framework that is popular for building APIs and single-
page applications.
● Spring Boot (for Java):
A popular framework for building RESTful web services and APIs in Java, known for its ease of use
and rapid development capabilities. www.roboleary.net provides a tutorial on building an API in Java
with Spring Boot.
256
Key Concepts:
● Restful APIs:
A common architectural style for building APIs that uses HTTP methods (GET, POST, PUT,
DELETE) to interact with resources.
● API-Driven Development:
A development approach that prioritizes the creation of APIs as the primary interface for web
applications, enabling flexibility and scalability.
● Web Application Frameworks:
Provide the necessary tools and structures for building web applications, including routing,
templating, and database interaction.
● Cloud Services:
Platforms like AWS, Azure, or Google Cloud provide APIs for managing cloud resources, enabling
web applications to leverage cloud computing for scalability, storage, and processing power.
257
Questions
1. Discuss the role of Spring Framework?
2. Explain dependency injection with example.
3. What do you mean by Spring Inversion of Control(IoC).
4. Implement Auto wring through example.
5. Discuss the role of Annotations in Spring Framework.
6. Discuss Spring Boot Code Structure.
7. What do you mean by Spring Boot Runners?
8. Explain Restful Web Services.
9. Discuss the role of GET, POST, PUT and DELETE request pareameters.
10. What is the role of request mapping and request body
258
MEERUT INSTITUTE OF ENGINEERING & TECHNOLOGY, MEERUT
Question Bank
CSE 2nd Year (Even Semester)
Subject Name: Object Oriented Programming with Java
Subject Code: BCS403
Unit-1(CO1)
1. What are the features of Java?
2. What is the difference between JDK, JRE, and JVM?
3. What is the difference between a class and an object?
4. What are the four principles of OOP?
5. What are access modifiers?
6. What is encapsulation, polymorphism, and abstraction?
7. What is a constructor? Explain types of constructor.
8. What do you understand by an instance variable and a local variable?
9. Explain the use of final keyword in variable, method and class.
10. When can you use super keyword?
11. Why is the main method static in Java?
12. Difference between static methods, static variables, and static classes in java.
13. What is the purpose of the static keyword in Java?
14. Explain the concept of inheritance with types in Java through examples
15. How do you create and use an array in Java?
16. What is method overloading and overriding with example in Java?
17. What is the purpose of the final keyword when used with a variable?
18. What is the difference between an abstract class and an interface?
19. Define Packages in Java. Explain the usage of Java packages
20. Explain steps to create package and import it with example.
Unit-2(CO2)
21. What is exception handling in Java and what are the advantages of exception handling?
22. Write a Java program that throws an exception and catch it using a try-catch block.
23. What is the difference between checked and unchecked exceptions in Java? Give examples of
each.
24. Explain the flow of control when an exception is thrown inside a try block. What happens if
there is no matching catch block?
25. What is the role of the finally block in exception handling? Can it be used without a catch block?
26. How do the throw and throws keywords differ in Java? Explain with code examples.
27. How would you create a custom (user-defined) exception in Java? When would you prefer to do
so over using built-in exceptions?
28. What is stream in java? Explain inputstream and outputstream class.
29. Explain FileInputStream and Fileoutputstream class with example.
30. What is the difference between byte streams and character streams in Java? When would you
use one over the other?
31. Explain Bufferedinputstream and BufferedOutputStream with eample.
32. Write a Java program that reads data from a file and writes it to another file using character
streams.
33. What are the two ways of implementing thread in Java?
34. What's the difference between thread and process?
35. Explain FileReader and FileWriter class with example.
36. Describe the life cycle of a thread in Java with a diagram or flow. What methods are used to
control the state transitions?
37. How do thread priorities affect the execution of threads in Java? Can thread priority guarantee
execution order?
38. What is inter-thread communication in Java? How are wait(), notify(), and notifyAll() used in this
context?
39. Explain Scanner class with example in java.