Oops Java
Oops Java
TECHNOLOGY MEERUT
Teachers’ Manual
CSE (AI&ML)
Mission of Institute
The mission of the institute is to educate young aspirants in various technical fields
to fulfill global requirements 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.
Lecture Delivery Plan:
Lecture-1
Lecture-2
2.2 Compilation
2.3 Fundamental
Lecture-3
3.2 Constructors
3.3 Methods
Lecture-4
4.2 Comments
4.4 Variables
4.5 Operators
Lecture-5
Lecture-7
Lecture-8
8.1 Abstraction
8.2 Interfaces
Lecture-9 Packages:
Lecture-10
Introduction:
Java is a class-based, object-oriented programming language that is designed to
have as few implementation dependencies as possible. It is intended to let
application developers write once, and run anywhere (WORA), meaning that
compiled Java code can run on all platforms that support Java without the need for
recompilation. Java was first released in 1995 and is widely used for developing
applications for desktop, web, and mobile devices. Java is known for its simplicity,
robustness, and security features, making it a popular choice for enterprise-level
applications.
History of Java:
JAVA was developed by James Gosling at Sun Microsystems Inc in the
year 1995 and later acquired by Oracle Corporation. It is a simple programming
language. Java makes writing, compiling, and debugging programming easy. It
helps to create reusable code and modular programs. Java is a class-based,
object-oriented programming language and is designed to have as few
implementation dependencies as possible. A general-purpose programming
language made for developers to write once run anywhere that is compiled Java
code can run on all platforms that support Java. Java applications are compiled to
byte code that can run on any Java Virtual Machine. The syntax of Java is similar to
c/c++.
History: Java’s history is very interesting. It is a programming language created in
1991. James Gosling, Mike Sheridan, and Patrick Naughton, a team of Sun
engineers known as the Green team initiated the Java language in 1991. Sun
Microsystems released its first public implementation in 1996 as Java 1.0. It
provides no-cost -run-times on popular platforms. Java1.0 compiler was re-written
in Java by Arthur Van Hoff to strictly comply with its specifications. With the
arrival of Java 2, new versions had multiple configurations built for different types
of platforms.
In 1997, Sun Microsystems approached the ISO standards body and later formalized
Java, but it soon withdrew from the process. At one time, Sun made most of its Java
implementations available without charge, despite their proprietary software status.
Sun generated revenue from Java through the selling of licenses for specialized
products such as the Java Enterprise System.
On November 13, 2006, Sun released much of its Java virtual machine as free,
open-source software. On May 8, 2007, Sun finished the process, making all of its
JVM’s core code available under open-source distribution terms.
The principles for creating java were simple, robust, secured, high-performance,
portable, multi-threaded, interpreted, dynamic, etc. In 1995 Java was developed
by James Gosling, who is known as the Father of Java. Currently, Java is used in
mobile devices, internet programming, games, e-business, etc.
Implementation of a Java application program involves a following step. They
include:
1. Creating the program
2. Compiling the program
3. Running the program
Remember that, before we begin creating the program, the Java Development Kit
(JDK) must be properly installed on our system and also path will be set.
• Compiling the program
To compile the program, we must run the Java compiler (javac), with the name of
the source file on “command prompt” like as follows:
If everything is OK, the “javac” compiler creates a file called “Test.class”
containing byte code of the program.
• Running the program
We need to use the Java Interpreter to run a program.
Java programming language is named JAVA. Why?
After the name OAK, the team decided to give it a new name to it and the
suggested words were Silk, Jolt, revolutionary, DNA, dynamic, etc. These all
names were easy to spell and fun to say, but they all wanted the name to reflect
the essence of technology. In accordance with James Gosling, Java the among
the top names along with Silk, and since java was a unique name so most of
them preferred it.
Java is the name of an island in Indonesia where the first coffee(named java coffee)
was produced. And this name was chosen by James Gosling while having coffee
near his office. Note that Java is just a name, not an acronym.
Java Terminology
Before learning Java, one must be familiar with these common terms of Java.
1. Java Virtual Machine(JVM): This is generally referred to as JVM. There are
three execution phases of a program. They are written, compile and run the
program.
● Writing a program is done by a java programmer like you and me.
● The compilation is done by the JAVAC compiler which is a primary Java
compiler included in the Java development kit (JDK). It takes the Java program
as input and generates bytecode as output.
● In the Running phase of a program, JVM executes the bytecode generated by the
compiler.
Now, we understood that the function of Java Virtual Machine is to execute the
bytecode produced by the compiler. Every Operating System has a different JVM
but the output they produce after the execution of bytecode is the same across all the
operating systems. This is why Java is known as a platform-independent
language.
1. Platform Independent: Compiler converts source code to bytecode and then the
JVM executes the bytecode generated by the compiler. This bytecode can run on
any platform be it Windows, Linux, or macOS which means if we compile a
program on Windows, then we can run it on Linux and vice versa. Each operating
system has a different JVM, but the output produced by all the OS is the same after
the execution of the bytecode. That is why we call java a platform-independent
language.
● The development tools are part of the system known as Java Development
Kit ( JDK ).
Java Virtual Machine(JVM): This is generally referred to as JVM. There are
three execution phases of a program. They are written, compile and run the
program.
● Writing a program is done by a java programmer like you and me.
● The compilation is done by the JAVAC compiler which is a primary Java
compiler included in the Java development kit (JDK). It takes the Java program
as input and generates bytecode as output.
● In the Running phase of a program, JVM executes the bytecode generated by the
compiler.
Now, we understood that the function of Java Virtual Machine is to execute the
bytecode produced by the compiler. Every Operating System has a different JVM
but the output they produce after the execution of bytecode is the same across all the
operating systems. This is why Java is known as a platform-independent
language.
class demo
{ // class definition
int x;
}
Compilation
First, the source ‘.java’ file is passed through the compiler, which then encodes the
source code into a machine-independent encoding, known as Bytecode. The content
of each class contained in the source file is stored in a separate ‘.class’ file. While
converting the source code into the bytecode, the compiler follows the following
steps:
What is the Compilation Process in Java?
The source code of a Java code is compiled into an intermediate binary code known
as the Bytecode during the Java compilation process. The machine cannot directly
execute this Bytecode. A virtual machine known as the Java Virtual Machine, or
JVM, understands it. JVM includes a Java interpreter that converts Bytecode to
target computer machine code. JVM is platform-specific, which means that each
platform has its own JVM. However, once the proper JVM is installed on the
machine, any Java Bytecode code can be run. This is shown in the diagram below:
Java application development (implementation) and can be broken down into the
following phases:
Compilation:
A special application called a compiler, executes our Java program on what is
known as a virtual Java machine (JVM).
The compiler transforms source code into so-called JVM bytecode, or machine code
read by JVM. In addition, the compiler should check the code for lexical and
semantic issues and optimise it.
.java file
.java file contains the source code . We will write our code in .java file like Sum of
two numbers ,Hello World, Java Application etc.
We need to convert source code to machine code so computer can understand.
But in Java , compiler/loader compiles the entire .java file into byte code and the
extension of that byte code is .class .
.class file
Byte Code — Some intermediate language of Java .This code will not directly run
on a system. We need JVM( Java Virtual Machine) to run this code.
JVM converts byte code into machine code line by line .Here JVM works as
Interpreter. .class file can be run on any operating system. This is the reason why
Java is platform independent.
More about platform independent — It means that byte code can run on all
operating systems.
Fundamental of Java:
Language Fundamentals” topic which includes the basic concepts to write programs
in Java.
Lecture-3
Defining Classes 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:
1. <access specifier> class class_name
2. {
3. // member variables
4. // class methods
5. }
Java Classes
A class in Java is a set of objects which shares common characteristics/ behavior
and common properties/ attributes. It is a user-defined blueprint or prototype from
which objects are created. For example, Student is a class while a particular student
named Ravi is an object.
Properties of Java Classes
1. Class is not a real-world entity. It is just a template or blueprint or prototype
from which objects are created.
2. Class does not occupy memory.
3. Class is a group of variables of different data types and a group of methods.
4. A Class in Java can contain:
● Data member
● Method
● Constructor
● Nested Class
● Interface
Class Declaration in Java
access_modifier class <class_name>
{
data member;
method;
constructor;
nested class;
interface;
}
Example of Java Class
class Student {
int id;
String name;
System.out.println(s1.id);
System.out.println(s1.name);
Constructor:
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.
What are Constructors in Java?
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 the constructor, memory for
the object is allocated in the memory. It is a special type of method that is used to
initialize the object. Every time an object is created using the new() keyword, at
least one constructor is called.
// Create a Main class
public Main() {
Main myObj = new Main(); // Create an object of class Main (This will call
the constructor)
JAVA METHOD
Advantage of Method
● Code Reusability
● Code Optimization
Note: Methods are time savers and help us to reuse the code without retyping the
code.
Method Declaration
Static members:
The static keyword in Java is mainly used for memory management. The static
keyword in Java is used to share the same variable or method of a given class. The
users can apply static keywords with variables, methods, blocks, and nested classes.
The static keyword belongs to the class than an instance of the class. The static
keyword is used for a constant variable or a method that is the same for every
instance of a class.
The static keyword is a non-access modifier in Java that is applicable for the
following:
1. Blocks
2. Variables
3. Methods
4. Classes
Example:
public class MyClass {
public static void sample(){
System.out.println("Hello");
}
public static void main(String args[]){
MyClass.sample();
}
}
● Shared memory allocation: Static variables and methods are allocated memory
space only once during the execution of the program. This memory space is
shared among all instances of the class, which makes static members useful for
maintaining global state or shared functionality.
● Accessible without object instantiation: Static members can be accessed
without the need to create an instance of the class. This makes them useful for
providing utility functions and constants that can be used across the entire
program.
● Associated with class, not objects: Static members are associated with the
class, not with individual objects. This means that changes to a static member are
reflected in all instances of the class, and that you can access static members
using the class name rather than an object reference.
● Cannot access non-static members: Static methods and variables cannot access
non-static members of a class, as they are not associated with any particular
instance of the class.
● Can be overloaded, but not overridden: Static methods can be overloaded,
which means that you can define multiple methods with the same name but
different parameters. However, they cannot be overridden, as they are associated
with the class rather than with a particular instance of the class.
When a member is declared static, it can be accessed before any objects of its class
are created, and without reference to any object. For example, in the below java
program, we are accessing static method m1() without creating any object of
the Test class.
Lecture-4:
Final Members:
Syntax:
1. /*
2. This
3. is
4. multi line
5. comment
6. */
byte 0 1 byte
short 0 2 byte
int 0 4 byte
long 0L 8 byte
byte byteValue1 = 2;
byte byteValue2 = 4;
byte byteResult = (byte)(byteValue1 + byteValue2);
short shortValue1 = 2;
short shortValue2 = 4;
short shortResult = (short)(shortValue1 + shortValue2);
int intValue1 = 2;
int intValue2 = 4;
int intResult = intValue1 + intValue2;
boolea true or 1
false true, false true, false
n false bit
twos-comp
8
lement 0 (none) -128 to 127
bits
byte integer
twos-comp
16
lement 0 (none) -32,768 to 32,767
bits
short integer
twos-comp -2,147,483,648
32
lement 0 -2,-1,0,1,2 to
bits
int intger 2,147,483,647
-9,223,372,036,854,775,8
twos-comp 08
64 -2L,-1L,0L,1
lement 0 to
bits L,2L
integer 9,223,372,036,854,775,80
long 7
Descriptio Defaul Siz Example
Type n t e Literals Range of values
1.23456e300
IEEE 754
64 d,
floating 0.0 upto 16 decimal digits
bits -123456e-30
point
double 0d , 1e1d
Variables in Java
Java variable is a name given to a memory location. It is the basic unit of storage in
a program.
● The value stored in a variable can be changed during program execution.
● Variables in Java are only a name given to a memory location. All the operations
done on the variable affect that memory location.
● In Java, all variables must be declared before use.
How to Declare Variables in Java?
We can declare variables in Java as pictorially depicted below as a visual aid.
1. datatype: Type of data that can be stored in this variable.
2. data_name: Name was given to the variable.
In this way, a name can only be given to a memory location. It can be assigned
values in two ways:
● Variable Initialization
● Assigning value by taking input
How to Initialize Variables in Java?
It can be perceived with the help of 3 components that are as follows:
● datatype: Type of data that can be stored in this variable.
● variable_name: Name given to the variable.
● value: It is the initial value stored in the variable.
Types of Variables
There are three types of variables in Java:
o local variable
o instance variable
o static variable
1) Local Variable
A variable declared inside the body of the method is called local variable. You can
use this variable only within that method and the other methods in the class aren't
even aware that the variable exists.
A local variable cannot be defined with "static" keyword.
2) Instance Variable
A variable declared inside the class but outside the body of the method, is called an
instance variable. It is not declared as static.
It is called an instance variable because its value is instance-specific and is not
shared among instances.
3) Static variable
A variable that is declared as static is called a static variable. It cannot be local. You
can create a single copy of the static variable and share it among all the instances of
the class. Memory allocation for static variables happens only once when the class
is loaded in the memory.
Example to understand the types of variables in java
1. public class A
2. {
3. static int m=100;//static variable
4. void method()
5. {
6. int n=90;//local variable
7. }
8. public static void main(String args[])
9. {
10. int data=50;//instance variable
11. }
12.}//end of class
● Arithmetic operators
● Assignment operators
● Comparison operators
● Logical operators
ARITHMETIC OPERATOR
In the example below, we use the assignment operator (=) to assign the value 10 to
a variable called x:
int x = 10;
Comparison operators are used to compare two values (or variables). This is
important in programming, because it helps us to find answers and make decisions.
&& Logical Returns true if both statements are x < 5 && x <
and true 10
! Logical Reverse the result, returns false if the !(x < 5 && x <
not result is true 10)
Java Operator Precedence
additive +-
equality == !=
bitwise exclusive OR ^
bitwise inclusive OR |
logical OR ||
Ternary ternary ?:
Lecture -5:
1) Simple if statement:
It is the most basic statement among all control flow statements in Java. It evaluates
a Boolean expression and enables the program to enter a block of code if the
expression evaluates to true.
Syntax of if statement is given below.
1. if(condition) {
2. statement 1; //executes when condition is true
3. }
2) if-else statement
The if-else statement is an extension to the if-statement, which uses another block of
code, i.e., else block. The else block is executed if the condition of the if-block is
evaluated as false.
Syntax:
1. if(condition) {
2. statement 1; //executes when condition is true
3. }
4. else{
5. statement 2; //executes when condition is false
6. }
3) if-else-if ladder:
1. if(condition 1) {
2. statement 1; //executes when condition 1 is true
3. }
4. else if(condition 2) {
5. statement 2; //executes when condition 2 is true
6. }
7. else {
8. statement 2; //executes when all the conditions are false
9. }
4. Nested if-statement
1. if(condition 1) {
2. statement 1; //executes when condition 1 is true
3. if(condition 2) {
4. statement 2; //executes when condition 2 is true
5. }
6. else{
7. statement 2; //executes when condition 2 is false
8. }
9. }
Ex: Example
System.out.println("Good morning.");
System.out.println("Good day.");
} else {
System.out.println("Good evening.");
ForExample.java
WhileExample.java
1. public class WhileExample {
2. public static void main(String[] args) {
3. int i=1;
4. while(i<=10){
5. System.out.println(i);
6. i++;
7. }
8. }
9. }
DoWhileExample.java
Disadvantages
o Size Limit: We can store only the fixed size of elements in the array. It
doesn't grow its size at runtime. To solve this problem, collection framework
is used in Java which grows automatically.
In such case, data is stored in row and column based index (also known as matrix
form).
1) String Literal
Java String literal is created by using double quotes. For Example:
1. String s="welcome";
Each time you create a string literal, the JVM checks the "string constant pool" first.
If the string already exists in the pool, a reference to the pooled instance is returned.
If the string doesn't exist in the pool, a new string instance is created and placed in
the pool. For example:
Classes: A class is a user defined blueprint or prototype from which objects are
created. It represents the set of properties or methods that are common to all objects
of one type. Classes are required in OOPs because:
● It provides template for creating objects, which can bind code into data.
● It has definitions of methods and data.
● It supports inheritance property of Object Oriented Programming and hence can
maintain class hierarchy.
● It helps in maintaining the access specifications of member variables.
Objects: It is the basic unit of Object Oriented Programming and it represents the
real life entities.
Real-life entities share two characteristics: they all have attributes and behaviour.
An object consists of:
● State: It is represented by attributes of an object. It also shows properties of an
object.
● Behaviour: It is represented by methods of an object. It shows response of an
object with other objects.
● Identity: It gives a unique name to an object. It also grants permission to one
object to interact with other objects.
Objects are required in OOPs because they can be created to call a non-static
function which are not present inside the Main Method but present inside the Class
and also provide the name to the space which is being used to store the data.
Example: For addition of two numbers, it is required to store the two numbers
separately from each other, so that they can be picked and the desired operations can
be performed on them. Hence creating two different objects to store the two
numbers will be an ideal solution for this scenario.
Example to demonstrate the use of Objects and classes in OOPs
OBJECTS
Objects relate to things found in the real world. For example, a graphics program
may have objects such as “circle”, “square”, “menu”. An online shopping system
might have objects such as “shopping cart”, “customer”, and “product”.
Declaring Objects (Also called instantiating a class)
When an object of a class is created, the class is said to be instantiated. All the
instances share the attributes and the behavior of the class. But the values of those
attributes, i.e. the state are unique for each object. A single class may have any
number of instances.
An entity that has state and behavior is known as an object e.g., chair, bike, marker,
pen, table, car, etc. It can be physical or logical (tangible and intangible). The
example of an intangible object is the banking system.
An object has three characteristics:
o State: represents the data (value) of an object.
o Behavior: represents the behavior (functionality) of an object such as
deposit, withdraw, etc.
o Identity: An object identity is typically implemented via a unique ID. The
value of the ID is not visible to the external user. However, it is used
internally by the JVM to identify each object uniquely.
For Example, Pen is an object. Its name is Reynolds; color is white, known as its
state. It is used to write, so writing is its behavior.
Object Definitions:
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.
o
Advantage of Method
o Code Reusability
o Code Optimization
The new keyword is used to allocate memory at runtime. All objects get memory in
Heap memory area.
Object and Class Example: main within the class
In this example, we have created a Student class which has two data members id
and name. We are creating the object of the Student class by new keyword and
printing the object's value.
Here, we are creating a main() method inside the class.
File: Student.java
//Java Program to illustrate how to define a class and fields
//Defining a Student class.
class Student{
//defining fields
int id;//field or data member or instance variable
String name;
//creating main method inside the Student class
public static void main(String args[]){
//Creating an object or instance
Student s1=new Student();//creating an object of Student
//Printing values of the object
System.out.println(s1.id);//accessing member through reference variable
System.out.println(s1.name);
}
There are 3 ways to initialize object in Java.
1. By reference variable
2. By method
3. By constructor
Inheritance in Java
Inheritance in Java is a mechanism in which one object acquires all the properties
and behaviors of a parent object. It is an important part of OOPs (Object Oriented
programming system).
The idea behind inheritance in Java is that you can create new classes that are built
upon existing classes. When you inherit from an existing class, you can reuse
methods and fields of the parent class. Moreover, you can add new methods and
fields in your current class also.
Inheritance represents the IS-A relationship which is also known as
a parent-child relationship.
Why use inheritance in java
o For Method Overriding (so runtime polymorphism can be achieved).
o For Code Reusability.
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.
1. class Employee{
2. float salary=40000;
3. }
4. class Programmer extends Employee{
5. int bonus=10000;
6. public static void main(String args[]){
7. Programmer p=new Programmer();
8. System.out.println("Programmer salary is:"+p.salary);
9. System.out.println("Bonus of Programmer is:"+p.bonus);
10.}
11.}
Multilevel Inheritance Example
File: TestInheritance2.java
1. class Animal{
2. void eat(){System.out.println("eating...");}
3. }
4. class Dog extends Animal{
5. void bark(){System.out.println("barking...");}
6. }
7. class BabyDog extends Dog{
8. void weep(){System.out.println("weeping...");}
9. }
10.class TestInheritance2{
11.public static void main(String args[]){
12.BabyDog d=new BabyDog();
13.d.weep();
14.d.bark();
15.d.eat();
16.}}
File: TestInheritance3.java
Q) Why Method Overloading is not possible by changing the return type of method
only?
In java, method overloading is not possible by changing the return type of the
method only because of ambiguity. Let's see how ambiguity may occur:
1. class Adder{
2. static int add(int a,int b){return a+b;}
3. static double add(int a,int b){return a+b;}
4. }
5. class TestOverloading3{
6. public static void main(String[] args){
7. System.out.println(Adder.add(11,11));//ambiguity
8. }
9. }
NOTE:-Compile Time Error: method add(int,int) is already defined in class
Adder
POINT:-System.out.println(Adder.add(11,11)); //Here, how can java
determine which sum() method should be called?
// Java Encapsulation
// Person Class
class Person {
// methods defined
// Driver Class
// main function
person.setName("John");
person.setAge(30);
// variables
ABSTRACT
In Java, abstract is a non-access modifier in java applicable for classes, and methods
but not variables. It is used to achieve abstraction which is one of the pillars of
Object Oriented Programming (OOP). Following are different contexts
where abstract can be used in Java.
Characteristics of Java abstract Keyword
In Java, the abstract keyword is used to define abstract classes and methods. Here
are some of its key characteristics:
● Abstract classes cannot be instantiated: An abstract class is a class that cannot
be instantiated directly. Instead, it is meant to be extended by other classes,
which can provide concrete implementations of its abstract methods.
● Abstract methods do not have a body: An abstract method is a method that
does not have an implementation. It is declared using the abstract keyword and
ends with a semicolon instead of a method body. Subclasses of an abstract class
must provide a concrete implementation of all abstract methods defined in the
parent class.
● Abstract classes can have both abstract and concrete methods: Abstract
classes can contain both abstract and concrete methods. Concrete methods are
implemented in the abstract class itself and can be used by both the abstract class
and its subclasses.
● Abstract classes can have constructors: Abstract classes can have constructors,
which are used to initialize instance variables and perform other initialization
tasks. However, because abstract classes cannot be instantiated directly, their
constructors are typically called constructors in concrete subclasses.
● Abstract classes can contain instance variables: Abstract classes can contain
instance variables, which can be used by both the abstract class and its
subclasses. Subclasses can access these variables directly, just like any other
instance variables.
● Abstract classes can implement interfaces: Abstract classes can implement
interfaces, which define a set of methods that must be implemented by any class
that implements the interface. In this case, the abstract class must provide
concrete implementations of all methods defined in the interface.
Overall, the abstract keyword is a powerful tool for defining abstract classes and
methods in Java. By declaring a class or method as abstract, developers can provide
a structure for subclassing and ensure that certain methods are implemented in a
consistent way across all subclasses.
Abstract Methods in Java
Sometimes, we require just method declaration in super-classes. This can be
achieved by specifying the abstract type modifier. These methods are sometimes
referred to as subclasser responsibility because they have no implementation
specified in the super-class. Thus, a subclass must override them to provide a
method definition. To declare an abstract method, use this general form:
Example of Abstract class that has an 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.
1. abstract class Bike{
2. abstract void run();
3. }
4. class Honda4 extends Bike{
5. void run(){System.out.println("running safely");}
6. public static void main(String args[]){
7. Bike obj = new Honda4();
8. obj.run();
9. }
10.}
Interface in Java
An interface in Java is a blueprint of a class. It has static constants and abstract
methods.
The interface in Java is a mechanism to achieve abstraction. There can be only
abstract methods in the Java interface, not method body. It is used to achieve
abstraction and multiple inheritance in Java.
In other words, you can say that interfaces can have abstract methods and variables.
It cannot have a method body.
Java Interface also represents the IS-A relationship.
In this example, the Printable interface has only one method, and its implementation
is provided in the A6 class.
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, Interface has only static and final variables.
non-final, static and non-static
variables.
4) Abstract class can provide the Interface can't provide the implementation
implementation of interface. of abstract class.
6) An abstract class can extend another An interface can extend another Java
Java class and implement multiple Java interface 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();
} }
1) Java package is used to categorize the classes and interfaces so that they can be
easily maintained.
2) Java package provides access protection.
3) Java package removes naming collision.
1) Using packagename.*
If you use package.* then all the classes and interfaces of this package will be
accessible but not subpackages.
The import keyword is used to make the classes and interface of another package
accessible to the current package.
Example of package that import the packagename.*
1. //save by A.java
2. package pack;
3. public class A{
4. public void msg(){System.out.println("Hello");}
5. }
1. //save by B.java
2. package mypack;
3. import pack.*;
4.
5. class B{
6. public static void main(String args[]){
7. A obj = new A();
8. obj.msg();
9. }
10.}
Output:Hello
2) Using packagename.classname
If you import package.classname then only declared class of this package will be
accessible.
// Main class
class GFG {
// Print statement
System.out.println("I/O classes are imported from java.io package");
}
}
This package provides for system input and output through data streams,
serialization, and the file system. Unless otherwise noted, passing a null argument to
a constructor or method in any class or interface in this package will cause a
NullPointerException to be thrown. All the classes listed here are imported or if we
want to import a specific one then do use it as stated below.
import java.util.Scanner ;
The JVM knows where to find the class Menu. Now, how will the JVM know this
location?
It is impractical for it to go through every folder on your system and search for it.
Thus, using the CLASSPATH variable we provide it the place where we want it to
look. We put directories and jars in the CLASSPATH variable.
Lecture-10
JAR FILE
A JAR (Java Archive) is a package file format typically used to aggregate many
Java class files and associated metadata and resources (text, images, etc.) into one
file to distribute application software or libraries on the Java platform.
In simple words, a JAR file is a file that contains a compressed version of .class
files, audio files, image files, or directories. We can imagine a .jar file as a zipped
file(.zip) that is created by using WinZip software. Even, WinZip software can be
used to extract the contents of a .jar . So you can use them for tasks such as lossless
data compression, archiving, decompression, and archive unpacking.
Let us see how to create a .jar file and related commands which help us to work
with .jar files
1.1 Create a JAR file
In order to create a .jar file, we can use jar cf command in the following ways as
Jar tf A.jar
Note: When we create .jar files, it automatically receives the default manifest file.
There can be only one manifest file in an archive, and it always has the pathname.
Jar xf A.jar
1.5 Running a JAR file
In order to run an application packaged as a JAR file (requires the Main-class
manifest header), the following command can be used as listed:
Syntax:
C:\>java -jar A.jar
● JAVA
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
6.3
● JAVA
class Test2 {
System.out.println(sqrt(4));
System.out.println(pow(2, 2));
System.out.println(abs(6.3));
Output:
2.0
4.0
6.3
● JAVA
class Geeks {
out.println(sqrt(4));
out.println(pow(2, 2));
out.println(abs(6.3));
Output:
2.0
4.0
6.3
NOTE : System is a class present in java.lang package and out is a static variable
present in System class. By the help of static import we are calling it without class
name.
UNIT-2
Lecture Delivery Plan:
Lecture-11
Lecture-12
Lecture-13
13.1 catch
13.2 finally
13.3 throw
Lecture-14
Lecture-15
Lecture-16
16.1 Thread
16.2 Thread Life Cycle
Lecture-17
Lecture-18
Lecture11
Exception Handling
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.
● Identifying unexpected events: Exceptions represent situations that deviate from the
program's expected behavior. This could be due to various reasons like:
o User errors: Entering invalid data, attempting forbidden actions.
o Resource limitations: Running out of memory, network issues.
o System errors: Hardware failures, software bugs.
● 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 catch and handle different types of exceptions.
o The try block contains the code that might potentially throw an exception.
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
In Java, an exception is an event that disrupts the normal flow of the program. It is
an object which is thrown at runtime.
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.
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.
MultipleCatchBlock1.java
TestFinallyBlock.java
Output:
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.
1. Performance Impact: Using exceptions as control flow can reduce the performance of the code as a
response per unit time
2. Readability: It makes the code less readable and hides the programmer's intention, which is
considered a bad practice
Instead of using exceptions for expected behaviours, it is recommended to use control flow statements to
handle the logic.
If the behaviours are expected, using control flow statements is generally considered better than throwing an
exception and handling it by yourself
Certainly! Here is a diagram illustrating the Java exception hierarchy and the various types
of exceptions:
+---------------------+
| Throwable |
+----------+----------+
+--------+--------+
| Error |
+-----------------+
| Exception |
+--------+--------+
+--------+--------+
| RuntimeException|
+--------+--------+
| Checked Exception|
+--------+--------+
|Unchecked Exception|
+-------------------+
In this hierarchy:
● Throwable is the base class for all exceptions and errors in Java.
● Error is used by the Java runtime system (JVM) to indicate errors related to the
runtime environment itself.
● Exception is used for exceptional conditions that user programs should catch. It has
two main branches:
o RuntimeException: These are unchecked exceptions that occur at runtime
and are not checked by the compiler.
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.
Exit
methodA
() Exit
main()
5.methodC() completes.
8.main() popped out from the call stack and completes. Program exits.
System.out.println("Enter methodC()");
The exception message clearly shows the method call stack trace with the relevant statement line numbers:
MethodC() triggers an ArithmeticException. As it does not handle this exception, it popped off from the call stack immediately.
MethodB() also does not handle this exception and popped off the call stack. So does methodA() and main() method. The main()
method passes back to JVM, which abruptly terminates the program and print the call stack trace, as shown.
The figure below shows the hierarchy of the Exception classes. The base class for all Exception objects is
The Error class describes internal system errors (e.g., VirtualMachineError, 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).
Use of try
Certainly! Here's a diagram illustrating the use of the try...catch block in Java:
try {
} catch (Exception e) {
} finally {
In this diagram:
● 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 that
executes when an exception is thrown.
● The finally block contains the code that always executes, regardless of whether an
exception was thrown or caught.
Lecture-13
CATCH
1.7 try-catch-finally
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 catch block).
Example 1
1 import java.util.Scanner; import
2 java.io.File;
3 import java.io.FileNotFoundException; public class
4 TryCatchFinally {
5 public static void main(String[] args) { try {
6 // main logic
7 System.out.println("Start of the main logic");
8 System.out.println("Try opening a file ..."); Scanner in = new
9 Scanner(new File("test.in"));
10
System.out.println("File Found, processing the file ..."); System.out.println("End of the main logic");
11
12 } catch (FileNotFoundException ex) { // error handling separated from the main logic
13 System.out.println("File Not Found caught ...");
14
} finally { // always run regardless of exception status
15
System.out.println("finally-block runs regardless of the state of exception");
16
}
17
// after the try-catch-finally
18
System.out.println("After try-catch-finally, life goes on...");
} finally { // finally is optional
// clean up codes, always executed regardless of exceptions
......
}
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 {
o // Block of code to try
o } catch(Exception e) {
o // Block of code to handle errors
o }
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.
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.
o Syntax:
o try {
o // Block of code to try
o } catch(Exception e) {
o // Block of code to handle errors
o } finally {
o // Block of code to execute regardless of an
exception
o }
o The finally block always executes, even if an exception is thrown and caught.
o It is often used to release resources like file handles, database connections, or
network connections, to ensure that these resources are properly closed or
released.
o The finally block is optional, but when used, it ensures that certain code will
always be executed, making it useful for cleanup or finalization tasks.
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.
o Syntax:
o 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.
●
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:
Lecture-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
Built-in Exception
Exceptions that are already available in Java libraries are referred to as built-in exception.
These exceptions are able to define the error situation so that we can understand the reason
of getting this error. It can be categorized into two broad categories, i.e., checked
exceptions and unchecked exception.
Checked Exception
Checked exceptions are called compile-time exceptions because these exceptions are
checked at compile-time by the compiler. The compiler ensures whether the programmer
handles the exception or not. The programmer should have to handle the exception;
otherwise, the system has shown a compilation error.
CheckedExceptionExample.java
1. import java.io.*;
2. class CheckedExceptionExample {
3. public static void main(String args[]) {
4. FileInputStream file_data = null;
5. file_data = new FileInputStream("C:/Users/ajeet/OneDrive/Desktop/Hello.txt");
6. int m;
7. while(( m = file_data.read() ) != -1) {
8. System.out.print((char)m);
9. }
10. file_data.close();
11. }
12. }
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:
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
1. class UncheckedExceptionExample1 {
2. public static void main(String args[])
3. {
4. int postive = 35;
5. int zero = 0;
6. int result = positive/zero;
7. //Give Unchecked Exception here.
8. System.out.println(result);
9. }
10. }
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:
ADVERTISEMENT
UncheckedException1.java
1. class UncheckedException1 {
2. public static void main(String args[])
3. {
4. int num[] ={10,20,30,40,50,60};
5. System.out.println(num[7]);
6. }
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.
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.
1. These exceptions are checked at compile These exceptions are just opposite to the
time. These exceptions are handled at checked exceptions. These exceptions are not
compile time too. checked and handled at compile time.
2. These exceptions are direct subclasses of They are the direct subclasses of the
exception but not extended from RuntimeException class.
RuntimeException class.
3. The code gives a compilation error in the The code compiles without any error because
case when a method throws a checked the exceptions escape the notice of the
exception. The compiler is not able to compiler. These exceptions are the results of
handle the exception on its own. user-created errors in programming logic.
4. These exceptions mostly occur when the These exceptions occur mostly due to
probability of failure is too high. programming mistakes.
6. These exceptions are propagated using the These are automatically propagated.
throws keyword.
7. It is required to provide the try-catch and In the case of unchecked exception it is not
try-finally block to handle the checked mandatory.
exception.
Lecture-15
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.
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.
5 FilterInputStream This class contains methods to read bytes from the other input streams,
which are used as the primary source of data.
7 PipedInputStream This class provides methods to read from a piped output stream to which
the piped input stream must be connected.
8 SequenceInputStream This class provides methods to connect multiple Input Stream and read
data from them.
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.
ADVERTISEMENT
SN Method Description
1 int read() This method returns an integer, an integral representation of the next available
byte of the input. The integer -1 is returned once the end of the input is
encountered.
2 int read (byte This method is used to read the specified buffer length bytes from the input
buffer []) 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 starting at a
buffer [], int loc, int specified location, 'loc'. It returns the total number of bytes successfully read
nBytes) 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 mark(int This method is used to mark the current position in the input stream until the
nBytes) specified nBytes are read.
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 and returns the
nBytes) 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.
SN Class Description
1 BufferedOutputStream This class provides methods to write the bytes to the buffer.
2 ByteArrayOutputStream This class provides methods to write bytes to the byte array.
3
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 write(bytes It is used to write nByte bytes to the output stream from the buffer
buffer[],int loc, int starting at the specified location.
nBytes)
4 void flush () It is used to flush the output stream and writes the pending buffered
bytes.
5 void close () It is used to close the output stream. However, if we try to close the
already closed output stream, the IOException will be thrown by this
method.
DataOutputStream This class provides methods to write the java primitive data types.
The OutputStream class provides various methods to write bytes to the output streams. The
methods are given in the following table.
Example:
The following example uses the ByteArrayInputStream to create an input stream from a byte
array "content". We use the read() method to read the content from an input stream. We have
also used the write() method on a FileOutputStream object to write the byte array content in
the file.
Consider the following example.
1. import java.io.ByteArrayInputStream;
2. import java.io.File;
3. import java.io.FileInputStream;
4. import java.io.FileNotFoundException;
5. import java.io.FileOutputStream;
6. import java.io.IOException;
7. public class InputOutputStreamExample {
8. public static void main(String[] args) throws IOException {
9. // TODO Auto-generated method stub
10. byte content[] = "Jtp is the best website to learn new technologies".getBytes();
11. ByteArrayInputStream inputStream = new ByteArrayInputStream(content);
12.
13. inputStream.read(content);
14.
15. File newFile = new File("/Users/MyUser/Desktop/MyNewFile.doc");
16. FileOutputStream outputStream = new FileOutputStream(newFile);
17. outputStream.write(content);
18.
19. }
20.
21.
22. }
Output:
A new file MyNewFile.doc will be created on desktop with the content "Jtp is the
best web
Reader Class
Reader class is used to read the 16-bit characters from the input stream. However, it is an
abstract class and can't be instantiated, but there are various subclasses that inherit the
Reader class and override the methods of the Reader class. All methods of the Reader class
throw an IOException. The subclasses of the Reader class are given in the following table.
SN Class Description
1. BufferedReader This class provides methods to read characters from the buffer.
2. CharArrayReader This class provides methods to read characters from the char array.
3. FileReader This class provides methods to read characters from the file.
4. FilterReader This class provides methods to read characters from the underlying character
input stream.
5 InputStreamReader This class provides methods to convert bytes to characters.
6 PipedReader This class provides methods to read characters from the connected piped
output stream.
SN Method Description
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 buffer at the
int loc, int nChars) 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 skip(long nChars) This method is used to skip the specified nChars characters from the input
stream and returns the number of characters skipped.
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.
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.
SN Class Description
3 CharArrayWriter This class provides methods to write the characters to the character array.
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.
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 write(char This method is used to write the array of characters to the output stream.
buffer[])
4 void write(char buffer This method is used to write the nChars characters to the character array
[],int loc, int nChars) from the specified location.
5 void close () This method is used to close the output stream. However, this generates
the IOException if an attempt is made to write to the output stream after
closing the stream.
6 void flush () This method is used to flush the output stream and writes the waiting
buffered characters.
To create a file in Java, you can use the createNewFile() method. This method
returns a boolean value: true if the file was successfully created, and false if the file
already exists. Note that the method is enclosed in a try...catch block. This is
necessary because it throws an IOException if an error occurs (if the file cannot be
created for some reason):
Write To a File
try {
myWriter.close();
} catch (IOException e) {
e.printStackTrace();
Lecture-16
Thread
Threads are independent. If there occurs exception in one thread, it doesn't affect other threads. It
uses a shared memory area.
A thread in Java at any point of time exists in any one of the following states. A
thread lies only in one of the shown states at any instant:
1. New State
2. Runnable State
3. Blocked State
4. Waiting State
5. Timed Waiting State
6. Terminated State
The diagram shown below represents various states of a thread at any instant in
time.
Lecture-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.
Example
● Java
import java.lang.*;
// Main class
// Method 1
// Print statement
// Thread 1
+ t1.getPriority());
// Thread 1
+ t2.getPriority());
// Thread 3
+ t3.getPriority());
t1.setPriority(2);
t2.setPriority(5);
t3.setPriority(8);
// IllegalArgumentException
// 2
+ t1.getPriority());
// 5
+ t2.getPriority());
// 8
System.out.println("t3 thread priority : "
+ t3.getPriority());
// Main thread
System.out.println(
+ Thread.currentThread().getName());
System.out.println(
+ Thread.currentThread().getPriority());
Thread.currentThread().setPriority(10);
System.out.println(
+ Thread.currentThread().getPriority());
}
}
Output
t1 thread priority : 5
t2 thread priority : 5
t3 thread priority : 5
t1 thread priority : 2
t2 thread priority : 5
t3 thread priority : 8
Currently Executing Thread : main
Main thread priority : 5
Main thread priority : 10
Output explanation:
● Thread with the highest priority will get an execution chance prior to other
threads. Suppose there are 3 threads t1, t2, and t3 with priorities 4, 6, and 1. So,
thread t2 will execute first based on maximum priority 6 after that t1 will execute
and then t3.
● The default priority for the main thread is always 5, it can be changed later. The
default priority for all other threads depends on the priority of the parent thread.
Lecture-18
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.
Types of Synchronization
There are two types of synchronization
Thread Synchronization
There are two types of thread synchronization mutual exclusive and inter-thread
communication.
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:
TestSynchronization1.java
100
10
200
15
300
20
400
25
500
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
ADVERTISEMENT
ADVERTISEMENT
o wait()
o notify()
o 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.
Method Description
public final void wait(long It waits for the specified amount of time.
timeout)throws
InterruptedException
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:
3) notifyAll() method
Wakes up all threads that are waiting on this object's monitor.
Syntax:
wait() sleep()
The wait() method releases the lock. The sleep() method doesn't
release the lock.
Test.java
Output:
going to withdraw...
going to deposit...
deposit completed...
withdraw completed
Lecture-20
Lecture-21
22.3 Try-withresources
Lecture-22
Lecture-23
Lecture-25
25.2 Records
Lecture-26
Functional Interface is also known as Single Abstract Method Interfaces or SAM Interfaces. It is
a new feature in Java, which helps to achieve functional programming approach.
Java 8 Stream
Java provides a new additional package in Java 8 called java.util.stream.
This package consists of class interfaces and enum to allows functional-style operations on
the elements. You can use stream by importing java.util.stream package.
Stream does not store elements. It simply conveys elements from a source such as a
o Stream is functional in nature. Operations performed on a stream does not modify it's
source.
o For example, filtering a Stream obtained from a collection produces a new Stream
without
o the filtered elements, rather than removing elements from the source collection.
o Stream is lazy and evaluates code only when required.
o The elements of a stream are only visited once during the life of a stream. Like an
Iterator,
o a new stream must be generated to revisit the same elements of the source.
You can use stream to filter, collect, print, and convert from one data structure to other etc.
In the following examples, we have apply various operations with the help of stream.
Lecture -20
Streams API
The first question we are going to address is how many points in total all OPEN
tasks have? Up to Java 8, the usual solution for it would be some sort of foreach
iteration. But in Java 8 the answers is streams: a sequence of elements supporting
sequential and parallel aggregate operations.
There are a couple of things going on here. Firstly, the tasks collection is
converted to its stream representation. Then, the filter operation on stream filters
out all CLOSED tasks. On next step, the mapToInt operation converts the
stream of Tasks to the stream of Integers using Task::getPoints method of the
each task instance. And lastly, all points are summed up using sum method,
producing the final result.
Before moving on to the next examples, there are some notes to keep in mind
about streams (more details here). Stream operations are divided into intermediate
and terminal operations.
Intermediate operations return a new stream. They are always lazy, executing an
intermediate operation such as filter does not actually perform any filtering, but
instead creates a new stream that, when traversed, contains the elements of the
initial stream that match the given predicate
Terminal operations, such as forEach or sum, may traverse the stream to produce
a result or a side-effect. After the terminal operation is performed, the stream
pipeline is considered consumed, and can no longer be used. In almost all cases,
terminal operations are eager, completing their traversal of the underlying data
source.
Yet another value proposition of the streams is out-of-the box support of parallel
processing. Let us take a look on this example, which does sums the points of all
the tasks.
It is very similar to the first example except the fact that we try to process all the
tasks in parallel and calculate the final result using reduce method.
Here is the console output:
To finish up with the tasks example, let us calculate the overall percentage (or
weight) of each task across the whole collection, based on its points.
The console output is just here:
And lastly, as we mentioned before, the Stream API is not only about Java collections. The
typical I/O operations like reading the text file line by line is a very good candidate to
benefit from stream processing. Here is a small example to confirm that.
The onClose method called on the stream returns an equivalent stream with an additional
close handler. Close handlers are run when the close() method is called on the stream.
Stream API together with Lambdas and Method References baked by Interface’s Default
and Static Methods is the Java 8 response to the modern paradigms in software
development. For more details, please refer to official documentation.
The LocalDateTime combines together LocaleDate and LocalTime and holds a date with
time but without a time-zone in the ISO-8601 calendar system. A quick example is shown
below.
If case you need a date/time for particular timezone, the ZonedDateTime is here to help.
It holds a date with time and with a time-zone in the ISO-8601 calendar system. Here are a
couple of examples for different timezones.
The example above computes the duration (in days and hours) between two dates, 16 April
2014 and 16 April 2015. Here is the sample output on a console:
he overall impression about Java 8’s new date/time API is very, very positive. Partially, because of the
Tt
battle-proved foundation it is built upon (Joda-Time), partially because this time it was finally tackled seriously and
developer voices have been heard. For more details please refer to official documentation.
The small code snippet below glues together the default methods and static methods from the
examples above.
Default methods implementation on JVM is very efficient and is supported by the byte
code instructions for method invocation. Default methods allowed existing Java interfaces
to evolve without breaking the compilation process. The good examples are the plethora of
methods added to java.util.Collection interface: stream(), parallelStream(), forEach(),
removeIf(), . . .
Though being powerful, default methods should be used with a caution: before declaring
method as default it is better to think twice if it is really needed as it may cause ambiguity
and compilation errors in complex hierarchies. For more details please refer to official
documentation.
And the last, fourth type is reference to instance method of particular class
instance the syntax instance::method. Please notice that method accepts
exactly one parameter of type Car.
MIME
It uses the Base64 alphabet as specified in RFC 2045 for encoding and decoding operations.
The encoded output must be represented in lines of no more than 76 characters each and
uses a carriage return '\r' followed immediately by a linefeed '\n' as the line separator. No
line separator is added to the end of the encoded output. All line separators or other
characters not found in the base64 alphabet table are ignored in decoding operation.
Java Default Methods
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.
Lecture -22
To deal with situation, Java 9 restructured JDK into set of modules so that we can use only
The module system includes various tools and options that are given below.
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.
a Java file module-info.java is required. This file also known as module descriptor and
o Module name
o What does it export
o What does it require?
Lecture-23
Java 9 Anonymous Inner Classes Improvement
Java 9 introduced a new feature that allows us to use diamond operator with anonymous
classes. Using the diamond with anonymous classes was not allowed in Java 7.
In Java 9, as long as the inferred type is denotable, we can use the diamond operator when
we create an anonymous inner class.
Data types that can be written in Java program like int, String etc are called denotable types.
Java 9 compiler is enough smart and now can infer type.
Note: This feature is included to Java 9, to add type inference in anonymous inner classes.
Let's see an example, in which we are using diamond operator with inner class without
specifying type.
With the help of Diamond operator, we can create an object without mentioning the
generic type on the right hand side of the expression. But the problem is it will only
work with normal classes.
};
}
}
Local variable type inference is a feature in Java 10 that allows the developer to
skip the type declaration associated with local variables (those defined inside
method definitions, initialization blocks, for-loops, and other blocks like if-else), and
the type is inferred by the JDK. It will, then, be the job of the compiler to figure out
the datatype of the variable.
class A {
System.out.println(x)
String message;
switch (number) {
case ONE:
message = "Got a 1";
break;
case TWO:
message = "Got a 2";
break;
default:
message = "More than 2";
}
Copy
Let’s convert this to a switch expression and use the yield keyword along with
the arrow operator:
String message = switch (number) {
case ONE -> {
yield "Got a 1";
}
case TWO -> {
yield "Got a 2";
}
default -> {
yield "More than 2";
}
};Copy
yield sets the value of the switch expression depending on the value of number.
2.2. yield with Colon Delimiter
We can also create a switch expression using yield with the colon delimiter:
String message = switch (number) {
case ONE:
yield "Got a 1";
case TWO:
yield "Got a 2";
default:
yield "More than 2";
};
This code behaves the same as in the previous section. But the arrow operator
is clearer and also less prone to forgetting yield (or break) statements.
We should note that we can’t mix colon and arrow delimiters within the
same switch expression.
TEXT BLOCK
Text blocks start with a “”” (three double-quote marks) followed by
optional whitespaces and a newline. The most simple example looks like
this:
String example = """
Example text""";
Note that the result type of a text block is still a String. Text blocks just provide
us with another way to write String literals in our source code.
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:
RECORD
As developers and software engineers, our aim is to always design ways to obtain
maximum efficiency and if we need to write less code for it, then that’s a blessing.
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.
System.out.println("Anjali Sharma");
}
}
Explanation of the above Example:
● Human is the parent class of Manish, Vartika, and Anjali. It is a sealed class so;
other classes cannot inherit it.
● Manish, Vartika, and Anjali are child classes of the Human class, and it is
necessary to make them either sealed, non-sealed, or final. Child classes of a
sealed class must be sealed, non-sealed, or final.
● If any class other than Manish, Vartika, and Anjali tries to inherit from
the Human class, it will cause a compiler error.
Lecture -24
Switch Expressions
Switch expressions were introduced as a preview feature in Java 12 and became a standard
feature in Java 14. They provide a more concise and expressive way to use the switch statement,
allowing it to be used as either a statement or an expression. Here's a summary of the key points
about switch expressions in Java:
Switch expressions in Java allow the switch statement to be used as an expression, resulting in a
single value.
They can use either traditional case : labels with fall through or new case ... -> labels without fall
through.
They may contain case L -> labels that eliminate the need for break statements to prevent fall
through.
The yield statement can be used to specify the value of a switch expression.
Example:
int numLetters = 0;
};
System.out.println(numLetters);
Benefits:
Switch expressions provide a more concise and readable alternative to traditional switch
statements, especially when the goal is to produce a result.
They eliminate the need for break statements and provide a more functional programming style.
Switch expressions were introduced as a preview feature in Java 12 and became a standard feature
in Java 14.
The feature was designed to simplify everyday coding and prepare the way for the use of pattern
matching
in switch statements.
Switch expressions in Java provide a more concise and expressive way to use the switch statement,
allowing it to be used as either a statement or an expression. This feature simplifies everyday
coding and prepares the way for the use of pattern matching in switch statements.
Yield Keyword
The yield keyword is used in various programming languages, including Python, JavaScript, C#,
and Java, with slightly different functionalities in each language. Here's a summary of the yield
keyword in different programming languages based on the provided search results:
in Java, the yield keyword is used within switch expressions to exit the switch and return a value
that becomes the value of the switch expression. It allows the value of a switch expression to be
assigned to a variable and provides an implicit check for covering all cases in the switch
expression. The yield keyword is used in different programming languages to create generator
functions, pause and resume generator functions, provide values in iterations, and exit switch
expressions with a return value. Each language has its own specific use case and syntax for the
yield keyword.
Lecture-25
Text Blocks
Text blocks in Java are a feature introduced in Java 13 as a preview and became a permanent
feature in Java 15. They provide a more concise and readable way to declare multi-line strings in
Java. Here's a summary
of the key points about text blocks in Java based on the provided search results:
The principal purpose of text blocks is to provide clarity by minimizing the Java syntax required to
render
Text blocks eliminate the need for explicit line terminators, string concatenations, and delimiters,
allowing for the embedding of code snippets and text sequences more or less as-is.
Usage:
Text blocks start with """ followed by optional whitespaces and a newline. For example:
Example text""";
Inside the text blocks, newlines and quotes can be used without the need for escaping line breaks.
This allows for the inclusion of literal fragments of HTML, JSON, SQL, or other content in a more
elegant and readable way.
Benefits:
Text blocks provide a more efficient and readable way to declare multi-line strings in Java,
especially when dealing with large or complex text content.
They enhance code readability and maintainability by eliminating the need for explicit escape
characters and concatenations.
Text blocks were introduced as a preview feature in Java 13 and refined in a second preview before
becoming a permanent feature in Java 15.
The feature was aimed at reducing the complexity of declaring and using multi-line string literals
in Java.
Text blocks in Java provide a more efficient and readable way to declare multi-line strings,
enhancing code readability and maintainability. They eliminate the need for explicit escape
characters and concatenations, making it easier to include literal fragments of various content types
in a more elegant and readable way.
Records
In Java, a record is a new type of class introduced in Java 14 that is designed to be a simple and
concise way to declare classes that are transparent holders for shallowly immutable data. Here's a
summary of the key points about records in Java:
Purpose of Records:
Records are designed to provide a compact syntax for declaring classes that are meant to be used
primarily for storing data.
They are immutable by default, meaning that their state cannot be changed after they are
constructed.
Records are declared using the record keyword followed by the name of the record and a list of
components, which are the data fields of the record.
Records automatically provide implementations for methods such as equals(), hashCode(), and
toString(), based on the components of the record.
Example:
In this example, the Point record declares two components, x and y, and automatically provides
implementations for equals(), hashCode(), and toString().
Benefits:
Records provide a more concise and readable way to declare classes that are intended for data
storage, reducing the amount of boilerplate code that needs to be written.
They promote immutability and are well-suited for use in functional programming and concurrent
environments.
Evolution of Records:
Records were introduced as a preview feature in Java 14 and became a standard feature in Java 16.
The feature was aimed at simplifying the development of classes meant for data storage and
promoting best practices for immutability and transparency.
Records in Java provide a concise and immutable way to declare classes that are primarily used for
storing data. They automatically generate implementations for common methods, reducing the
need for boilerplate code and promoting best practices for immutability and transparency.
Lecture-26
Sealed Classe
In Java, sealed classes were introduced as a preview feature in Java 15 and became a
standard
feature in Java 17.
Sealed classes provide a way to control the inheritance hierarchy of a class or interface by
specifying
Which classes can extend or implement it.
Here's a summary of the key points about sealed classes in Java based on the provided
search results:
1. Syntax and Usage:
o Sealed classes are declared using the sealed modifier in their declaration.
o After any extends and implements clauses, the permits clause specifies the
classes that are permitted to extend the sealed class or implement the sealed
interface.
2. Purpose and Benefits:
o Sealed classes provide a more fine-grained control over inheritance in Java,
allowing classes and interfaces to define their permitted subtypes.
o This feature is useful for domain modeling and increasing the security of
libraries, as it enables the specification of which classes can implement or
extend a particular class or interface.
3. Evolution and Status:
o Sealed classes were proposed by JEP 360 and delivered in JDK 15 as a preview
feature. They were refined and delivered in JDK 16 as a preview feature with
no changes from JDK 16 to JDK 17.
o With the release of Java 17, sealed classes have become a permanent feature,
providing more control over the inheritance hierarchy.
Lecture-27
27.1 Collections in java
27.2 Hierarchy of collection framework
27.3 Iterable, collector and list interface
Lecture-28
28.1 ArrayList
28.2 LinkedList
28.3 Vector
Lecture-29
29.1 Stack
Lecture-30
30.2 HashSet
30.3 LinkedHashSet
Lecture-31
31.1 SortedSet
31.2 TreeSet
Lecture-32
Lecture-27
Collections 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).
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.
List Interface
List interface is the child interface of Collection interface. It inhibits a list type data structure
in which we can store the ordered collection of objects. It can have duplicate values.
List interface is implemented by the classes ArrayList, LinkedList, Vector, and Stack.
To instantiate the List interface, we must use :
1. List <data-type> list1= new ArrayList();
2. List <data-type> list2 = new LinkedList();
3. List <data-type> list3 = new Vector();
4. List <data-type> list4 = new Stack();
There are various methods in List interface that can be used to insert, delete, and access the
elements from the list.
The classes that implement the List interface are given below.
Lecture-28
The classes that implement the List interface are given below.
ArrayList
The ArrayList class is a resizable array, which can be found in the java.util package. The
difference between a built-in array and an ArrayList in Java, is that the size of an array
cannot be modified (if you want to add or remove elements to/from an array, you have to
create a new one).
How the ArrayList works
The ArrayList class has a regular array inside it. When an element is added, it is
placed into the array. If the array is not big enough, a new, larger array is created
to replace the old one and the old one is removed.
The ArrayList class implements the List interface. It uses a dynamic array to store the
duplicate element of different data types. The ArrayList class maintains the insertion order
and is non-synchronized. The elements stored in the ArrayList class can be randomly
accessed. Consider the following example.
1. import java.util.*;
2. class TestJavaCollection1{
3. public static void main(String args[]){
4. ArrayList<String> list=new ArrayList<String>();//Creating arraylist
5. list.add("Ravi");//Adding object in arraylist
6. list.add("Vijay");
7. list.add("Ravi");
8. list.add("Ajay");
9. //Traversing list through Iterator
10. Iterator itr=list.iterator();
11. while(itr.hasNext()){
12. System.out.println(itr.next());
13. }
14. }
15. }
Output:
Ravi
Vijay
Ravi
Ajay
LinkedList
The LinkedList class is a collection which can contain many objects of the same
type, just like the ArrayList.
The LinkedList class has all of the same methods as the ArrayList class
because they both implement the List interface. This means that you can add
items, change items, remove items and clear the list in the same way.
However, while the ArrayList class and the LinkedList class can be used in the
same way, they are built very differently.
LinkedList implements the Collection interface. It uses a doubly linked list internally to store
the elements. It can store the duplicate elements. It maintains the insertion order and is not
synchronized. In LinkedList, the manipulation is fast because no shifting is required.
Consider the following example.
1. import java.util.*;
2. public class TestJavaCollection2{
3. public static void main(String args[]){
4. LinkedList<String> al=new LinkedList<String>();
5. al.add("Ravi");
6. al.add("Vijay");
7. al.add("Ravi");
8. al.add("Ajay");
9. Iterator<String> itr=al.iterator();
10. while(itr.hasNext()){
11. System.out.println(itr.next());
12. }
13. }
14. }
Output:
Ravi
Vijay
Ravi
Ajay
Vector
The Vector class implements a growable array of objects. Vectors fall in legacy
classes, but now it is fully compatible with collections. It is found in java.util
package and implement the List interface, so we can use all the methods of the
List interface as shown below as follows:
● Vector implements a dynamic array which means it can grow or shrink as
required. Like an array, it contains components that can be accessed using an
integer index.
● They are very similar to ArrayList, but Vector is synchronized and has some
legacy methods that the collection framework does not contain.
● It also maintains an insertion order like an ArrayList. Still, it is rarely used in a
non-thread environment as it is synchronized, and due to this, it gives a poor
performance in adding, searching, deleting, and updating its elements.
● The Iterators returned by the Vector class are fail-fast. In the case of concurrent
modification, it fails and throws the ConcurrentModificationException.
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.
Lecture-29
Stack
Java Collection framework provides a Stack class that models and implements
a Stack data structure. The class is based on the basic principle of
last-in-first-out. In addition to the basic push and pop operations, the class
provides three more functions of empty, search, and peek. The class can also be
said to extend Vector and treats the class as a stack with the five mentioned
functions. The class can also be referred to as the subclass of Vector.
The below diagram shows the hierarchy of the Stack class:
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.
Queue Interface
The Queue interface is present in java.util package and extends the Collection interface is
used to hold the elements about to be processed in FIFO(First In First Out) order. It is an
ordered list of objects with its use limited to inserting elements at the end of the list and
deleting elements from the start of the list, (i.e.), it follows the FIFO or the
First-In-First-Out principle.
Being an interface the queue needs a concrete class for the declaration and the most
common classes are the PriorityQueue and LinkedList in Java. Note that neither of these
implementations is thread-safe. PriorityBlockingQueue is one alternative implementation if
the thread-safe implementation is needed.
Queue interface maintains the first-in-first-out order. It can be defined as an ordered list
that is used to hold the elements which are about to be processed. There are various classes
like PriorityQueue, Deque, and ArrayDeque which implements the Queue interface.
Queue interface can be instantiated as:
1. Queue<String> q1 = new PriorityQueue();
2. Queue<String> q2 = new ArrayDeque();
There are various classes that implement the Queue interface, some of them are given
below.
PriorityQueue
A PriorityQueue is used when the objects are supposed to be processed based on the
priority. It is known that a Queue follows the First-In-First-Out algorithm, but sometimes
the elements of the queue are needed to be processed according to the priority, that’s when
the PriorityQueue comes into play.
The PriorityQueue is based on the priority heap. The elements of the priority queue are
ordered according to the natural ordering, or by a Comparator provided at queue
construction time, depending on which constructor is used.
In the below priority queue, an element with a maximum ASCII value will have the highest
priority.
The PriorityQueue class implements the Queue interface. It holds the elements or objects
which are to be processed by their priorities. PriorityQueue doesn't allow null values to be
stored in the queue.
Consider the following example.
1. import java.util.*;
2. public class TestJavaCollection5{
3. public static void main(String args[]){
4. PriorityQueue<String> queue=new PriorityQueue<String>();
5. queue.add("Amit Sharma");
6. queue.add("Vijay Raj");
7. queue.add("JaiShankar");
8. queue.add("Raj");
9. System.out.println("head:"+queue.element());
10. System.out.println("head:"+queue.peek());
11. System.out.println("iterating the queue elements:");
12. Iterator itr=queue.iterator();
13. while(itr.hasNext()){
14. System.out.println(itr.next());
15. }
16. queue.remove();
17. queue.poll();
18. System.out.println("after removing two elements:");
19. Iterator<String> itr2=queue.iterator();
20.while(itr2.hasNext()){
21. System.out.println(itr2.next());
22. }
23.}
24. }
Output:
head:Amit Sharma
head:Amit Sharma
iterating the queue elements:
Amit Sharma
Raj
JaiShankar
Vijay Raj
after removing two elements:
Raj
Vijay Raj
Deque Interface
The Deque (double-ended queue) interface in Java is a subinterface of the Queue
interface and extends it to provide a double-ended queue, which is a queue that
allows elements to be added and removed from both ends. The Deque interface is
part of the Java Collections Framework and is used to provide a generic and
flexible data structure that can be used to implement a variety of algorithms and
data structures.
Deque interface extends the Queue interface. In Deque, we can remove and add the
elements from both the side. Deque stands for a double-ended queue which enables us to
perform the operations at both the ends.
ArrayDeque
The ArrayDeque class in Java is an implementation of the Deque interface that uses a
resizable array to store its elements. This class provides a more efficient alternative to the
traditional Stack class, which was previously used for double-ended operations. The
ArrayDeque class provides constant-time performance for inserting and removing elements
from both ends of the queue, making it a good choice for scenarios where you need to
perform many add and remove operations.
ArrayDeque class implements the Deque interface. It facilitates us to use the Deque. Unlike
queue, we can add or delete the elements from both the ends.
ArrayDeque is faster than ArrayList and Stack and has no capacity restrictions.
Consider the following example.
1. import java.util.*;
2. public class TestJavaCollection6{
3. public static void main(String[] args) {
4. //Creating Deque and adding elements
5. Deque<String> deque = new ArrayDeque<String>();
6. deque.add("Gautam");
7. deque.add("Karan");
8. deque.add("Ajay");
9. //Traversing elements
10. for (String str : deque) {
11. System.out.println(str);
12. }
13. }
14. }
Output:
Gautam
Karan
Ajay
Lecture-30
Set Interface
The set interface is present in java.util package and extends the Collection
interface. It is an unordered collection of objects in which duplicate values cannot
be stored. It is an interface that implements the mathematical set. This interface
contains the methods inherited from the Collection interface and adds a feature
that restricts the insertion of the duplicate elements. There are two interfaces that
extend the set implementation
HashSet
Java HashSet class implements the Set interface, backed by a hash table which is
actually a HashMap instance. No guarantee is made as to the iteration order of the
hash sets which means that the class does not guarantee the constant order of
elements over time. This class permits the null element. The class also offers
constant time performance for the basic operations like add, remove, contains, and
size assuming the hash function disperses the elements properly among the
buckets, which we shall see further in the article.
Declaration of HashSet
Output:
Vijay
Ravi
Ajay
LinkedHashSet
The LinkedHashSet is an ordered version of HashSet that maintains a
doubly-linked List across all elements. When the iteration order is needed to be
maintained this class is used. When iterating through a HashSet the order is
unpredictable, while a LinkedHashSet lets us iterate through the elements in the
order in which they were inserted. When cycling through LinkedHashSet using an
iterator, the elements will be returned in the order in which they were inserted.
The Hierarchy of LinkedHashSet is as follows:
Lecture-31
SortedSet Interface
The SortedSet interface present in java.util package extends the Set interface
present in the collection framework. It is an interface that implements the
mathematical set. This interface contains the methods inherited from the Set
interface and adds a feature that stores all the elements in this interface to be
stored in a sorted manner.
A Map doesn't allow duplicate keys, but you can have duplicate values. HashMap and
LinkedHashMap allow null keys and values, but TreeMap doesn't allow any null key or value.
Java HashMap
Java HashMap class implements the Map interface which allows us to store key and value
pair, where keys should be unique. If you try to insert the duplicate key, it will replace the
element of the corresponding key. It is easy to perform operations using the key index like
updation, deletion, etc. HashMap class is found in the java.util package.
HashMap in Java is like the legacy Hashtable class, but it is not synchronized. It allows us to
store the null elements as well, but there should be only one null key. Since Java 5, it is
denoted as HashMap<K,V>, where K stands for key and V for value. It inherits the
AbstractMap class and implements the Map interface.
Points to remember
o Java HashMap contains values based on the key.
o Java HashMap contains only unique keys.
o Java HashMap may have one null key and multiple null values.
o Java HashMap is non synchronized.
o Java HashMap maintains no order.
o The initial default capacity of Java HashMap class is 16 with a load factor of 0.75.
SortedSet is the alternate of Set interface that provides a total ordering on its elements. The
elements of the SortedSet are arranged in the increasing (ascending) order. The SortedSet
provides the additional methods that inhibit the natural ordering of the elements.
The SortedSet can be instantiated as:
1. SortedSet<data-type> set = new TreeSet();
TreeSet
TreeSet is one of the most important implementations of the SortedSet interface in
Java that uses a Tree for storage. The ordering of the elements is maintained by a
set using their natural ordering whether or not an explicit comparator is provided.
This must be consistent with equals if it is to correctly implement the Set interface.
Java TreeSet class implements the Set interface that uses a tree for storage. Like HashSet,
TreeSet also contains unique elements. However, the access and retrieval time of TreeSet is
quite fast. The elements in TreeSet stored in ascending order.
Consider the following example:
1. import java.util.*;
2. public class TestJavaCollection9{
3. public static void main(String args[]){
4. //Creating and adding elements
5. TreeSet<String> set=new TreeSet<String>();
6. set.add("Ravi");
7. set.add("Vijay");
8. set.add("Ravi");
9. set.add("Ajay");
10. //traversing elements
11. Iterator<String> itr=set.iterator();
12. while(itr.hasNext()){
13. System.out.println(itr.next());
14. }
15. }
16. }
Output:
Ajay
Ravi
Vijay
LinkedHashMap in Java
The LinkedHashMap Class is just like HashMap with an additional feature of maintaining
an order of elements inserted into it. HashMap provided the advantage of quick insertion,
search, and deletion but it never maintained the track and order of insertion, which the
LinkedHashMap provides where the elements can be accessed in their insertion order.
Important Features of a LinkedHashMap are listed as follows:
● A LinkedHashMap contains values based on the key. It implements the Map interface
and extends the HashMap class.
● It contains only unique elements.
● It may have one null key and multiple null values.
● It is non-synchronized.
● It is the same as HashMap with an additional feature that it maintains insertion order.
For example, when we run the code with a HashMap, we get a different order of
elements.
Declaration:
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>
Here, K is the key Object type and V is the value Object type
● K – The type of the keys in the map.
● V – The type of values mapped in the map.
It implements Map<K, V> interface, and extends HashMap<K, V> class. Though the
Hierarchy of LinkedHashMap is as depicted in below media as follows:
● Hash: All the input keys are converted into a hash which is a shorter form of the key
so that the search and insertion are faster.
● Key: Since this class extends HashMap, the data is stored in the form of a key-value
pair. Therefore, this parameter is the key to the data.
● Value: For every key, there is a value associated with it. This parameter stores the
value of the keys. Due to generics, this value can be of any form.
● Next: Since the LinkedHashMap stores the insertion order, this contains the address
to the next node of the LinkedHashMap.
● Previous: This parameter contains the address to the previous node of the
LinkedHashMap.
Lecture-32
Sorting in Java
Whenever we do hear sorting algorithms come into play such as selection sort, bubble sort,
insertion sort, radix sort, bucket sort, etc but if we look closer here we are not asked to use
any kind of algorithms. It is as simple sorting with the help of linear and non-linear data
structures present within java. So there is sorting done with the help of brute force in java
with the help of loops and there are two in-built methods to sort in Java.
Ways of sorting in Java
1. Using loops
2. Using sort() method of Arrays class
3. Using sort method of Collections class
4. Sorting on a subarray
Let us discuss all four of them and propose a code for each one of them.
Java Comparable interface
Java Comparable interface is used to order the objects of the user-defined class. This
interface is found in java.lang package and contains only one method named
compareTo(Object). It provides a single sorting sequence only, i.e., you can sort the elements
on the basis of single data member only. For example, it may be rollno, name, age or
anything else.
Collections class
Collections class provides static methods for sorting the elements of collections. If collection
elements are of Set or Map, we can use TreeSet or TreeMap. However, we cannot sort the
elements of List. Collections class provides methods for sorting the elements of List type
elements.
ADVERTISEMENT
Method of Collections class for sorting List elements is used to sort the elements of
List by the given comparator.
public void sort(List list, ComparatorClass c)
To sort a given List, ComparatorClass must implement a Comparator interface.
Internally the Sort method does call Compare method of the classes it is sorting.
To compare two elements, it asks “Which is greater?” Compare method returns -1,
0, or 1 to say if it is less than, equal, or greater to the other. It uses this result to
then determine if they should be swapped for their sort.
Properties Class in Java
●
The Properties class represents a persistent set of properties. The Properties can
be saved to a stream or loaded from a stream. It belongs
to java.util package. Properties define the following instance variable. This variable
holds a default property list associated with a Properties object.
Properties defaults: This variable holds a default property list associated with a
Properties object.
Constructors of Properties
1. Properties(): This creates a Properties object that has no default values.
Properties p = new Properties();
2. Properties(Properties propDefault): The second creates an object that
uses propDefault for its default value.
Properties p = new Properties(Properties propDefault);
UNIT-5
Lecture Delivery Plan:
Lecture-33
Lecture-34
34.1 AOP
Lecture-35
35.1 Autowiring
35.2 Annotations
Lecture-36
4.4 Logger
Lecture-37
Lecture-38
Lecture-39
Lecture-40
It was developed by Rod Johnson in 2003. Spring framework makes the easy development
of JavaEE application.
Spring Framework
Spring is a lightweight framework. It can be thought of as a framework of
frameworks because it provides support to various frameworks such as Struts, Hibernate,
Tapestry, EJB, JSF, etc. The framework, in broader sense, can be defined as a structure where
we find solution of the various technical problems.
The Spring framework comprises several modules such as IOC, AOP, DAO, Context, ORM,
WEB MVC etc. We will learn these modules in next page. Let's understand the IOC and
Dependency Injection first.
1) Predefined Templates
Spring framework provides templates for JDBC, Hibernate, JPA etc. technologies. So there is
no need to write too much code. It hides the basic steps of these technologies.
Let's take the example of JdbcTemplate, you don't need to write the code for exception
handling, creating connection, creating statement, committing transaction, closing
connection etc. You need to write the code of executing query only. Thus, it save a lot of
JDBC code.
2) Loose Coupling
The Spring applications are loosely coupled because of dependency injection.
3) Easy to test
The Dependency Injection makes easier to test the application. The EJB or Struts application
require server to run the application but Spring framework doesn't require server.
4) Lightweight
Spring framework is lightweight because of its POJO implementation. The Spring Framework
doesn't force the programmer to inherit any class or implement any interface. That is why it
is said non-invasive.
5) Fast Development
The Dependency Injection feature of Spring Framework and it support to various
frameworks makes the easy development of JavaEE application.
6) Powerful abstraction
It provides powerful abstraction to JavaEE specifications such as JMS, JDBC, JPA and JTA.
7) Declarative support
It provides declarative support for caching, validation, transactions and formatting.
Consider you have an application which has a text editor component and you want to
provide a spell check. Your standard code would look something like this −
public TextEditor() {
spellChecker = new SpellChecker();
}
Here, we have removed total control from the TextEditor and kept it
somewhere else (i.e. XML configuration file) and the dependency (i.e.
class SpellChecker) is being injected into the class TextEditor through
a Class Constructor. Thus the flow of control has been "inverted" by
Dependency Injection (DI) because you have effectively delegated
dependances to some external system.
LECTURE-34
AOP in Spring Framework
Aspect oriented programming(AOP) as the name suggests uses aspects in
programming. It can be defined as the breaking of code into different modules,
also known as modularisation, where the aspect is the key unit of modularity.
Aspects enable the implementation of crosscutting concerns such as- transaction,
logging not central to business logic without cluttering the code core to its
functionality. It does so by adding additional behaviour that is the advice to the
existing code. For example- Security is a crosscutting concern, in many methods in
an application security rules can be applied, therefore repeating the code at every
method, define the functionality in a common class and control were to apply that
functionality in the whole application.
Dominant Frameworks in AOP:
AOP includes programming methods and frameworks on which modularisation of
code is supported and implemented. Let’s have a look at
A cross-cutting concern is a concern that can affect the whole application and should be
centralized in one location in code as possible, such as transaction management,
authentication, logging, security etc.
BEAN SCOPE
Bean Definition: In Spring, the objects that form the backbone of your application
and that are managed by the Spring IoC container are called beans. A bean is an
object that is instantiated, assembled, and otherwise managed by a Spring IoC
container.
Bean Scopes refers to the lifecycle of Bean that means when the object of Bean
will be instantiated, how long does that object live, and how many objects will be
created for that bean throughout. Basically, it controls the instance creation of the
bean and it is managed by the spring container.
Singleton Scope:
If the scope is a singleton, then only one instance of that bean will be instantiated
per Spring IoC container and the same instance will be shared for each request.
That is when the scope of a bean is declared singleton, then whenever a new
request is made for that bean, spring IOC container first checks whether an
instance of that bean is already created or not. If it is already created, then the IOC
container returns the same instance otherwise it creates a new instance of that
bean only at the first request. By default, the scope of a bean is a singleton.
Prototype Scope:
If the scope is declared prototype, then spring IOC container will create a new
instance of that bean every time a request is made for that specific bean. A
request can be made to the bean instance either programmatically
using getBean() method or by XML for Dependency Injection of secondary type.
Generally, we use the prototype scope for all beans that are stateful, while the
singleton scope is used for the stateless beans.
Request Scope
In request scope, container creates a new instance for each and every HTTP
request. So, if the server is currently handling 50 requests, then the container can
have at most 50 individual instances of the bean class. Any state change to one
instance, will not be visible to other instances. A bean instance is destructed as
soon as the request is completed.
Session Scope
In session scope, the application context creates a new instance for each and
every HTTP session. So, if the server has 20 active sessions, then the container
can have at most 20 individual instances of the bean class. All HTTP requests
within a single session lifetime will have access to the same single bean instance
in that session scope.
Any state change to one instance will not be visible to other instances. An
instance is destructed as soon as the session ends.
Application Scope
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.
WebSocket Scope
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.
LECTURE-35
Autowiring in Spring
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
This mode tells the framework that auto wiring is not supposed to
No
be done. It is the default mode used by Spring.
Advantage of Autowiring
It requires the less code because we don't need to write the code to inject the dependency
explicitly.
Disadvantage of Autowiring
No control of programmer.
Annotations
Annotations are a form of metadata that provides data about a program.
Annotations are used to provide supplemental information about a program. It
does not have a direct effect on the operation of the code they annotate. It does
not change the action of the compiled program. So in this article, we are going to
discuss what are the main types of annotation that are available in the spring
framework with some examples.
Use of java annotations
● Compiler instructions
● Build-time instructions
● Runtime instructions
Compiler instructions: Java provides the 3 in built annotations which
are used to give certain instructions to the compiler. Java in built
annotation are @Deprecated, @Override & @SuppressWarnings.
A java annotation always starts with the symbol @ and followed by the
annotation name. The @symbol signals the compiler that this is an
annotation.
Syntax:
@AnnotationName
Example:
@Entity
Here @ symbol signals the compiler that this is an annotation and the
Entity is the name of this annotation.An annotation can contain zero,
one or multiple elements. We have to set values for these
elements. Example:
@Entity(tableName = "USERS")
Where we can use annotations?
We can use java annotations above classes, interfaces, methods, fields
and local variables. Here is an example annotation added above a class
definition:
@Entity
public class Users {
}
1. Spring bean life cycle involves initialization and destruction callbacks and
Spring bean aware classes.
2. Initialization callback methods execute after dependency injection is
completed. Their purposes are to check the values that have been set in
bean properties, perform any custom initialization or provide a wrapper on
original bean etc. Once the initialization callbacks are completed, bean is
ready to be used.
3. When IoC container is about to remove bean, destruction callback
methods execute. Their purposes are to release the resources held by bean
or to perform any other finalization tasks.
4. When more than one initialization and destructions callback methods
have been implemented by bean, then those methods execute in certain
order.
LECTURE-36
Spring Boot
Spring Boot is most commonly used and contains all Spring
Framework features. Nowadays Spring Boot is becoming the best choice
for Java developers to build rapid Spring applications. When Java
Developers use Spring Boot for developing applications then they will
focus on the logic instead of struggling with the configuration setup
environment of the application.
In Spring Boot, choosing a build system is an important task. We
recommend Maven or Gradle as they provide a good support for
dependency management. Spring does not support well other build
systems.
Dependency Management
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. Remember that when you upgrade the Spring Boot version,
dependencies also will upgrade automatically.
Note − If you want to specify the version for dependency, you can
specify it in your configuration file. However, the Spring Boot team
highly recommends that it is not needed to specify the version for
dependency.
Maven Dependency
For Maven configuration, we should inherit the Spring Boot Starter
parent project to manage the Spring Boot Starters dependencies.
We should specify the version number for Spring Boot Parent Starter
dependency. Then for other starter dependencies, we do not need to
specify the Spring Boot version number.
Gradle Dependency
We can import the Spring Boot Starters dependencies directly
into build.gradle file. We do not need Spring Boot start Parent
dependency like Maven for Gradle.
Default package
A class that does not have any package declaration is considered as
a default package. Note that generally a default package declaration is
not recommended. Spring Boot will cause issues such as
malfunctioning of Auto Configuration or Component Scan, when you
use default package.
Application Runner
Application Runner is an interface used to execute the code after the
Spring Boot application started.
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. Spring Boot offers flexible logging
capabilities by providing various logging frameworks and also provides ways to manage
and configure the logs.
Why to use Spring Boot – Logging?
A good logging infrastructure is necessary for any software project as it not only helps in
understanding what’s going on with the application but also to trace any unusual incident
or error present in the project. This article covers several ways in which logging can be
enabled in a spring boot project through easy and simple configurations. Let’s first do the
initial setup to explore each option in more depth.
Lecture-37
Introduction to RESTful Web Services
REST stands for REpresentational State Transfer. It is developed by Roy Thomas Fielding,
who also developed HTTP. The main goal of RESTful web services is to make web
services more effective. RESTful web services try to define services using the different
concepts that are already present in HTTP. REST is an architectural approach, not a protocol.
It does not define the standard message exchange format. We can build REST services with
both XML and JSON. JSON is more popular format with REST. The key abstraction is a
resource in REST. A resource can be anything. It can be accessed through a Uniform
Resource Identifier (URI). For example:
The resource has representations like XML, HTML, and JSON. The current state capture by
representational resource. When we request a resource, we provide the representation of
the resource. The important methods of HTTP are:
o GET: It reads a resource.
o PUT: It updates an existing resource.
o POST: It creates a new resource.
o DELETE: It deletes the resource.
For example, if we want to perform the following actions in the social media application, we
get the corresponding results.
POST /users: It creates a user.
GET /users/{id}: It retrieves the detail of a user.
GET /users: It retrieves the detail of all users.
DELETE /users: It deletes all users.
DELETE /users/{id}: It deletes a user.
GET /users/{id}/posts/post_id: It retrieve the detail of a specific post.
POST / users/{id}/ posts: It creates a post of the user.
Further, we will implement these URI in our project.
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.3 Aug 2022
RestController: RestController is used for making restful web services with the help of
the @RestController annotation. This annotation is used at the class level and allows the
class to handle the requests made by the client. Let’s understand @RestController
annotation using an example. The RestController allows to handle all REST APIs such
as GET, POST, Delete, PUT requests.
Lecture-38
When building robust APIs, understanding and appropriately utilizing the HTTP methods GET, POST,
PUT, and DELETE is essential. Each method serves a specific purpose and has its own limitations. In
this article, we will explore these HTTP methods, their characteristics, and discuss their limitations in
the context of building robust APIs. Additionally, we will provide Java code examples to demonstrate
their usage.
1. Resource Manipulation: HTTP methods allow clients to perform various operations on
resources, such as retrieving data, submitting data, updating data, or deleting data. Each method
represents a specific action that can be taken on a resource, enabling a wide range of
interactions between clients and servers.
2. Uniform Interface: HTTP methods provide a uniform interface for interacting with web
resources. By adhering to the standard set of methods, clients and servers can communicate
effectively, regardless of the underlying technologies or platforms being used. This promotes
interoperability and simplifies the development and integration of web applications.
3. Intent and Semantics: Each HTTP method carries a specific intent and semantic meaning,
making it easier for developers to understand the purpose of an API endpoint by looking at the
method used. For example, a GET request is used to retrieve data, while a POST request is used
to submit data for processing or storage. By selecting the appropriate method, developers can
convey the intended operation more accurately.
4. Idempotence and Safety: HTTP methods have different characteristics regarding idempotence
and safety. Idempotence means that making multiple identical requests should have the same
outcome. Safe methods, such as GET, should not cause any modifications or side effects on the
server. Understanding these characteristics helps developers design APIs that adhere to the
expected behavior and minimize unintended side effects or data inconsistencies.
5. RESTful Architecture: HTTP methods play a fundamental role in building RESTful APIs
(Representational State Transfer). REST is an architectural style that leverages HTTP methods
to provide a scalable and flexible approach to designing web services. Each resource in a
RESTful API is typically associated with a specific URL, and the appropriate HTTP method is
used to interact with that resource.
By understanding and utilizing the appropriate HTTP methods, developers can build robust and
well-designed APIs that adhere to the principles of HTTP and REST. This ensures consistency,
interoperability, and efficiency in the communication between clients and servers.
Below we will elaborate more on the most commonly used HTTP methods.
GET Method:
The GET method is one of the fundamental HTTP methods used for retrieving data from a server. It is
designed to be safe, meaning it should not modify any data on the server. When using the GET method,
the client requests a representation of a resource from the server.
Here are some key points to consider when working with the GET method in API development:
1. Retrieving Data: The primary purpose of the GET method is to retrieve data from the server. It
is commonly used to fetch resources such as user profiles, product information, blog articles,
and more. The client sends a GET request to a specific URL, and the server responds with the
requested data.
2. Request Parameters: GET requests can include parameters in the URL to provide additional
information to the server. These parameters are appended to the URL as query parameters,
typically in the form of key-value pairs. For example, a GET request to retrieve user
information for a specific ID could look like: GET /users?id=123. The server can use these
parameters to filter or modify the returned data accordingly.
3. Idempotence: The GET method is considered idempotent, meaning that multiple identical GET
requests should have the same outcome. It implies that making multiple GET requests for the
same resource should not result in any unintended side effects or modifications on the server. It
allows caching mechanisms to be employed for efficient retrieval and reduces the risk of
unintentional changes or inconsistencies.
4. Response Codes: The server responds to a GET request with an appropriate HTTP response
code to indicate the success or failure of the request. The most common response code is 200
(OK), indicating that the request was successful, and the requested resource is returned in the
response body. Other possible response codes include 404 (Not Found) if the requested resource
does not exist, or 500 (Internal Server Error) if there was an error on the server while
processing the request.
5. Limitations: While the GET method is crucial for retrieving data, it has certain limitations to
consider:
o Data Length: GET requests have limitations on the length of the URL. Excessive data in the
URL can result in truncation, errors, or security vulnerabilities. It is recommended to keep
the data size within reasonable limits and consider alternative methods (e.g., POST) for large
payloads.
o Security Considerations: Since GET requests expose the data in the URL, it is important to
avoid including sensitive information like passwords or authentication tokens in the query
parameters. Instead, consider using other secure methods such as headers or request bodies
for transmitting sensitive data.
Java Code Example:
import java.net.HttpURLConnection;
01
import java.net.URL;
02
03 import java.io.BufferedReader;
04 import java.io.InputStreamReader;
05
06 public class GetExample {
07 public static void main(String[] args) {
08 try {
09 URL url = new URL("https://api.example.com/resource");
HttpURLConnection connection = (HttpURLConnection)
10
url.openConnection();
11 connection.setRequestMethod("GET");
12
13 int responseCode = connection.getResponseCode();
14 if (responseCode == HttpURLConnection.HTTP_OK) {
15 BufferedReader reader =
16 new BufferedReader(new
17 InputStreamReader(connection.getInputStream()));
18 String line;
19 StringBuilder response = new StringBuilder();
20 while ((line = reader.readLine()) != null) {
21 response.append(line);
}
22 reader.close();
23 System.out.println("Response: " + response.toString());
24 } else {
25 System.out.println("Error: " + responseCode);
26 }
27 connection.disconnect();
28 } catch (Exception e) {
29 e.printStackTrace();
30 }
}
31 }
In the given Java code example, the GET request is sent to https://api.example.com/resource.
The response from the server is then read and stored in a StringBuilder for further processing. If the
response code is 200 (HTTP_OK), the response is printed to the console.
while the GET method is efficient for retrieving data, it should not be used for operations that
modify the server state. For such operations, other HTTP methods like POST, PUT, or DELETE
should be employed.
POST Method:
The POST method is one of the HTTP methods used for submitting data to be processed by
the server. Unlike the GET method, which is used for retrieving data, the POST method is
intended for data submission and can cause modifications on the server. Here are some
important points to consider when working with the POST method:
1. Submitting Data: The primary purpose of the POST method is to submit data to the
server for processing or storage. This data can be in various formats such as form data,
JSON, XML, or binary data. The POST request typically includes a request body that
contains the data being sent to the server.
2. Idempotence: Unlike the GET method, the POST method is generally considered
non-idempotent. This means that multiple identical POST requests may have different
outcomes or effects on the server. For example, submitting the same POST request
multiple times may result in the creation of multiple resources or duplicate entries.
3. Request Headers: POST requests often include specific headers to provide additional
information about the request or the format of the data being sent. For example, the
“Content-Type” header specifies the format of the data in the request body, such as
“application/json” or “application/x-www-form-urlencoded”.
4. Response Codes: Similar to other HTTP methods, the server responds to a POST request
with an appropriate HTTP response code to indicate the success or failure of the request.
The common response code for a successful POST request is 201 (Created), indicating
that the resource has been successfully created on the server. Other possible response
codes include 200 (OK) for general success or 400 (Bad Request) for invalid or malformed
requests.
5. Limitations: While the POST method is commonly used for data submission, it also has
some limitations to consider:
o Lack of Idempotence: As mentioned earlier, the non-idempotent nature of the POST
method means that repeated identical requests may lead to unintended side effects. It
is important to design APIs in a way that handles duplicate submissions appropriately
and ensures data integrity.
o Lack of Caching: By default, POST requests are typically not cacheable. Caching is
important for improving performance and reducing the load on the server. If caching is
required for POST requests, additional measures such as Cache-Control headers or
server-side caching strategies need to be implemented.
Java Code Example:
01 t java.net.HttpURLConnection;
02 t java.net.URL;
03 t java.io.DataOutputStream;
04
05 c class PostExample {
06 ublic static void main(String[] args) {
07 try {
08 URL url = new URL("https://api.example.com/resource");
09 HttpURLConnection connection = (HttpURLConnection)
10 url.openConnection();
connection.setRequestMethod("POST");
11 connection.setDoOutput(true);
12
13 String postData = "data=example";
14 DataOutputStream outputStream = new
15 DataOutputStream(connection.getOutputStream());
16 outputStream.writeBytes(postData);
17 outputStream.flush();
outputStream.close();
18
19
int responseCode = connection.getResponseCode();
20
if (responseCode == HttpURLConnection.HTTP_OK) {
21 // Process response
22
} else {
23 // Handle error
24 }
25 connection.disconnect();
26 } catch (Exception e) {
e.printStackTrace();
}
Remember to use the appropriate HTTP method based on the intended operation. While the
GET method is used for retrieving data, the POST method is suitable for submitting data for
processing or creating new resources on the server.
PUT Method:
The PUT method is an HTTP method used for updating or replacing a resource on the server.
It is idempotent, meaning that multiple identical PUT requests should have the same
outcome. Here are some important points to consider when working with the PUT method:
1. Updating Resources: The primary purpose of the PUT method is to update an existing
resource on the server. It replaces the entire resource with the new representation
provided in the request. The PUT request typically includes a request body containing the
updated data for the resource.
2. Idempotence: As mentioned earlier, the PUT method is idempotent. It means that
making multiple identical PUT requests should have the same outcome. This property
allows for safe retries of failed requests without causing unintended side effects or data
inconsistencies.
3. Resource Identification: To update a specific resource, the client must provide the
unique identifier or URL of the resource in the PUT request. The server uses this
information to locate the resource and perform the update operation. It is crucial to
ensure the accuracy and integrity of the resource identification mechanism to prevent
unintended modifications to unrelated resources.
4. Partial Updates: By default, the PUT method replaces the entire resource with the new
representation provided in the request body. However, in some cases, it may be desirable
to perform partial updates, modifying only specific fields or properties of the resource.
While the HTTP specification does not directly support partial updates with the PUT
method, some APIs implement custom conventions or use additional operations (e.g.,
PATCH) to achieve partial updates.
5. Response Codes: Similar to other HTTP methods, the server responds to a PUT request
with an appropriate HTTP response code to indicate the success or failure of the request.
The common response code for a successful PUT request is 200 (OK), indicating that the
resource has been successfully updated. Alternatively, if the resource does not exist and a
new resource is created, the response code may be 201 (Created).
6. Limitations: While the PUT method is commonly used for resource updates, it also has
some limitations to consider:
o Lack of Partial Updates: As mentioned earlier, the PUT method typically replaces the
entire resource rather than allowing partial updates to specific fields. If partial updates
are required, alternative approaches like PATCH or custom conventions can be
considered.
o Security Considerations: It is essential to implement proper authentication,
authorization, and validation mechanisms to ensure that only authorized clients can
update the resources. Additionally, input validation should be performed to prevent
invalid or malicious data from being stored.
Java Code Example:
import java.net.HttpURLConnection;
01
import java.net.URL;
02
03 import java.io.DataOutputStream;
04
05 public class PutExample {
06 public static void main(String[] args) {
07 try {
08 URL url = new URL("https://api.example.com/resource");
HttpURLConnection connection = (HttpURLConnection)
09 url.openConnection();
10 connection.setRequestMethod("PUT");
11 connection.setDoOutput(true);
12
13 String putData = "data=updated";
14 DataOutputStream outputStream = new
15 DataOutputStream(connection.getOutputStream());
outputStream.writeBytes(putData);
16 outputStream.flush();
17 outputStream.close();
18
19 int responseCode = connection.getResponseCode();
20 if (responseCode == HttpURLConnection.HTTP_OK) {
21 // Process response
22 } else {
// Handle error
23 }
24 connection.disconnect();
25 } catch (Exception e) {
26 e.printStackTrace();
27 }
28 }
}
29
30
In the provided Java code example, a PUT request is sent
to https://api.example.com/resource with a request body containing the updated data.
The data is written to the request output stream, and the response code is checked to handle
the response accordingly.
When using the PUT method, it is important to handle concurrency and data consistency
issues appropriately. For example, you may use optimistic locking mechanisms or versioning
to ensure that updates do not conflict with other concurrent modifications to the resource.
Remember to use the appropriate HTTP method based on the intended operation. While the
GET method is used for retrieving data and the POST method is used for submitting data, the
PUT method is suitable for updating existing resources on the server.
DELETE Method:
The DELETE method is an HTTP method used for deleting a specified resource on the server.
It is used to remove a resource permanently from the server. Here are some important points
to consider when working with the DELETE method:
1. Deleting Resources: The primary purpose of the DELETE method is to delete a specific
resource on the server. The client sends a DELETE request to the server, specifying the
URL or identifier of the resource to be deleted.
2. Idempotence: Similar to the PUT method, the DELETE method is also idempotent.
Multiple identical DELETE requests should have the same outcome. Making repeated
DELETE requests for the same resource should not result in any unintended side effects or
modifications on the server.
3. Resource Identification: To delete a specific resource, the client must provide the
unique identifier or URL of the resource in the DELETE request. The server uses this
information to locate and remove the corresponding resource. It is crucial to ensure the
accuracy and integrity of the resource identification mechanism to prevent accidental
deletions of unrelated resources.
4. Response Codes: The server responds to a DELETE request with an appropriate HTTP
response code to indicate the success or failure of the request. The common response
code for a successful DELETE request is 204 (No Content), indicating that the resource has
been successfully deleted. Alternatively, if the resource does not exist, the response code
may be 404 (Not Found).
5. Limitations: While the DELETE method is commonly used for resource deletion, it is
important to consider the following limitations:
o Lack of Safety: Unlike the GET method, which is considered safe and should not
modify any data on the server, the DELETE method performs irreversible actions. Once a
resource is deleted, it cannot be easily recovered. Therefore, it is crucial to implement
appropriate authorization and authentication mechanisms to ensure that only authorized
clients can initiate DELETE requests.
o Cascading Deletions: In some cases, deleting a resource may have cascading effects
on related resources. For example, deleting a user may require deleting associated
records such as posts or comments. It is essential to define the behavior and potential
cascading actions in your API’s design and documentation.
Java Code Example:
01 import java.net.HttpURLConnection;
02
import java.net.URL;
03
04
public class DeleteExample {
05
public static void main(String[] args) {
06
try {
07
URL url = new URL("https://api.example.com/resource/123");
08 HttpURLConnection connection = (HttpURLConnection)
09 url.openConnection();
10 connection.setRequestMethod("DELETE");
11
12 int responseCode = connection.getResponseCode();
13 if (responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
14 // Resource deleted successfully
15 } else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND) {
16 // Resource not found
17 } else {
// Handle other errors
18 }
19 connection.disconnect();
20 } catch (Exception e) {
21 e.printStackTrace();
22 }
23 }
}
24
In the provided Java code example, a DELETE request is sent
to https://api.example.com/resource/123, where “123” represents the identifier of the
resource to be deleted. The response code is checked to handle the success or failure of the
deletion operation.
When using the DELETE method, it is important to implement proper authorization and
authentication mechanisms to prevent unauthorized deletions. Additionally, consider providing
proper error handling and feedback to the client in case of failures or errors during the
deletion process.
Remember to use the appropriate HTTP method based on the intended operation. While the
GET method is used for retrieving data, the POST method is used for submitting data, the
PUT method is used for updating data, the DELETE method is specifically designed for
resource deletion.
GET:
● Use Case: Retrieving Data
● Description: The GET method is used to retrieve data from a specified resource on the
server.
● Example: Fetching a user’s profile information from an API endpoint:
1 URL url = new URL("https://api.example.com/users/123");
2 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
3 connection.setRequestMethod("GET");
4
5 // Process the response
POST:
● Use Case: Submitting Data
● Description: The POST method is used to submit data to be processed or stored by the
server.
● Example: Creating a new user by sending data in the request body:
01 URL url = new URL("https://api.example.com/users");
02 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
03 connection.setRequestMethod("POST");
04 connection.setDoOutput(true);
05
06 // Set the request body with user data
07 DataOutputStream outputStream = new
DataOutputStream(connection.getOutputStream());
08 String userData = "name=John&[email protected]";
09 outputStream.writeBytes(userData);
10 outputStream.flush();
11 outputStream.close();
12
// Process the response
13
PUT:
● Use Case: Updating Data
● Description: The PUT method is used to update or replace a specified resource on the
server.
● Example: Updating a user’s information by sending the updated data in the request body:
01 URL url = new URL("https://api.example.com/users/123");
02 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
03 connection.setRequestMethod("PUT");
04 connection.setDoOutput(true);
05
// Set the request body with updated user data
06
07 DataOutputStream outputStream = new
DataOutputStream(connection.getOutputStream());
08 String updatedUserData = "name=John Smith&[email protected]";
09 outputStream.writeBytes(updatedUserData);
10 outputStream.flush();
11 outputStream.close();
12
// Process the response
13
DELETE:
● Use Case: Deleting Data
● Description: The DELETE method is used to delete a specified resource from the server.
● Example: Deleting a user by sending a DELETE request to the corresponding API
endpoint:
1 URL url = new URL("https://api.example.com/users/123");
2 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
3 connection.setRequestMethod("DELETE");
4
5 // Process the response
These examples demonstrate how the HTTP methods can be used in different scenarios to
perform common operations on resources. It’s important to note that these are just simplified
examples, and in real-world scenarios, you would typically handle error handling,
authentication, and other considerations to build robust and secure APIs.
Understanding the characteristics and limitations of the HTTP methods GET, POST, PUT, and
DELETE is crucial for building robust APIs. Each method serves a specific purpose and should
be used appropriately to ensure data integrity and consistent behavior. By leveraging these
HTTP methods effectively, developers can design APIs that are efficient, secure, and reliable.
Lecture-39
RequestMapping
One of the most important annotations in spring is
the @RequestMapping Annotation which is used to map HTTP requests to
handler methods of MVC and REST controllers. In Spring MVC applications, the
DispatcherServlet (Front Controller) is responsible for routing incoming HTTP
requests to handler methods of controllers. When configuring Spring MVC, you
need to specify the mappings between the requests and handler methods. To
configure the mapping of web requests, we use
the @RequestMapping annotation. The @RequestMapping annotation can be
applied to class-level and/or method-level in a controller. The class-level
annotation maps a specific request path or pattern onto a controller. You can then
apply additional method-level annotations to make mappings more specific to
handler methods. So let’s understand @RequestMapping Annotation at
Method-level and Class level by examples.
Requirements:
● Eclipse (EE version)/STS IDE
● Spring JAR Files
● Tomcat Apache latest version
Spring Boot is the most popular framework of Java for building enterprise-level
web applications and back-ends. Spring Boot has a handful of features that
support quicker and more efficient web app development. Some of them are
Auto-configuration, Embedded Server, opinionated defaults, and Annotation
Support. In this article, we’ll be exploring the core annotation of Spring Boot –
@RequestMapping which is part of the set of annotations that Spring Boot
employs for defining URL endpoints and REST APIs.
@RequestMapping
This annotation is a versatile and flexible annotation that can be used with a
controller (class) as well as the methods to map specific web requests with the
handler methods and controllers. This annotation is part of a larger set of
annotations provided by Spring Framework to define URL endpoints and simplify
the development of Spring Boot applications.
It has the following features:
● Define several different endpoints to access a specific resource.
● Build REST APIs to serve web requests.
● Simplify the web development process by simply defining an annotation that
offers a set of functionalities for handling requests.
● Define multiple endpoints in a single @RequestMapping annotation.
● Spring provides @RequestBody annotation to deserialize the incoming payload into java
object or map.
● The request body goes along with content-type header for handler method to understand
and deserialize the payload.
We can also use the @Valid annotation to automatically validate the input.
In brief, the @RequestBody annotation is responsible for retrieving the request
body and automatically converting it to the Java object.
path variable in spring boot
The @PathVariable annotation is used to retrieve data from the URL path. By
defining placeholders in the request mapping URL, you can bind those
placeholders to method parameters annotated with @PathVariable. This allows
you to access dynamic values from the URL and use them in your code.
The @PathVariable annotation is used to retrieve data from the URL path. By
defining placeholders in the request mapping URL, you can bind those
placeholders to method parameters annotated with @PathVariable. This allows
you to access dynamic values from the URL and use them in your code.
Using @PathVariable
The @PathVariable annotation is used to extract data from the URL path. It allows
you to define placeholders in your request mapping URL and bind those
placeholders to method parameters. Let’s consider an example where you have a
REST API endpoint for retrieving a user’s details by their ID:
o RestController: RestController is used for making restful web services with
the help of the @RestController annotation. This annotation is used at the
class level and allows the class to handle the requests made by the client.
Let’s understand @RestController annotation using an example. The
RestController allows to handle all REST APIs such
as GET, POST, Delete, PUT requests.
o Spring Initializr is a web-based tool using which we can easily generate the
structure of the Spring Boot project. It also provides various different
features for the projects expressed in a metadata model. This model allows
us to configure the list of dependencies that are supported by JVM. Here, we
will create the structure of an application using a spring initializer and then
use an IDE to create a sample GET route.
Lecture-40
Java provides some technologies like Servlet and JSP that allow us to develop and deploy a web
application on a server easily. It also provides some frameworks such as Spring, Spring Boot that
simplify the work and provide an efficient way to develop a web application. They reduce the
effort of the developer.
We can create a website using static HTML pages and style them using CSS, but we need
server-side technology when we want to create a dynamic website.
In this section, we will see how to create a website using Java Servlets and HTML. Further, we
will see how these technologies are useful for developing a web application.
What is Servlet
A Servlet is a Java program that runs within a web server; it receives the requests and
responds to them using related protocols (Usually HTTP). The Servlets are capable enough
to respond to any type of request; they are commonly used to make the application
functional.
We can create a static website using only HTML and CSS, but when it comes to dynamic,
we need a server-side programming language. For these applications, Java provides Servlet
technology, which contains HTTP-specific servlet classes.
The javax.servlet and javax.servlet.http packages contain interfaces and classes for creating
servlets. All servlets should implement the Servlet interface, which defines life-cycle
methods. To implement a generic service, we can use the GenericServlet class by extending
it. It provides doGet and doPost methods to handle HTTP-specific services.
Navigate to the directory where you have installed your server and select
the servlet-api.jar file.