[Go to site: main page, start]

0% found this document useful (0 votes)
2 views233 pages

Java Notes (All Modules)

Uploaded by

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

Java Notes (All Modules)

Uploaded by

Swasti Tyagi
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

MODULE – 1

Concepts of Object-Oriented Programming


(OOP) in Java
Object-Oriented Programming (OOP) is a programming paradigm based on the concept of
objects. Java is an object-oriented language, which means it heavily relies on OOP principles
for designing and structuring code.

1. Principles of OOP
OOP is based on four fundamental principles:

1. Encapsulation
2. Abstraction
3. Inheritance
4. Polymorphism

These principles help in writing modular, reusable, and maintainable code.

1. Encapsulation
Encapsulation is the mechanism of binding data (variables) and methods (functions) that
operate on the data into a single unit called a class. It restricts direct access to some of an
object's components, which helps in data hiding and protection.

Key Features:

 Data Hiding: Prevents direct access to the class’s internal data.


 Getter and Setter Methods: Used to access and modify private variables.
 Access Modifiers: Define the visibility of class members.

Example:
class Student {
private String name; // Private variable

// Setter method
public void setName(String newName) {
[Link] = newName;
}

// Getter method
public String getName() {
return name;
}
}

public class Main {


public static void main(String[] args) {
Student s = new Student();
[Link]("Alice");
[Link]([Link]()); // Output: Alice
}
}

Advantages: ✔ Protects data from unintended modifications.


✔ Improves code maintainability.

2. Abstraction
Abstraction is the process of hiding implementation details and showing only the necessary
functionalities.

Key Features:

 Focuses on "What" rather than "How".


 Implemented using Abstract Classes and Interfaces in Java.

Example using an Abstract Class:


abstract class Animal {
abstract void makeSound(); // Abstract method with no implementation

void sleep() { // Concrete method


[Link]("Sleeping...");
}
}

class Dog extends Animal {


@Override
void makeSound() {
[Link]("Bark!");
}
}

public class Main {


public static void main(String[] args) {
Dog d = new Dog();
[Link](); // Output: Bark!
[Link](); // Output: Sleeping...
}
}

Example using an Interface:


interface Vehicle {
void start();
}
class Car implements Vehicle {
@Override
public void start() {
[Link]("Car is starting...");
}
}

public class Main {


public static void main(String[] args) {
Car myCar = new Car();
[Link](); // Output: Car is starting...
}
}

Advantages: ✔ Reduces code complexity.


✔ Increases flexibility and security.

3. Inheritance
Inheritance allows one class (child class) to acquire the properties and behaviors of another
class (parent class). It promotes code reuse.

Types of Inheritance in Java:

1. Single Inheritance – One class inherits another.


2. Multilevel Inheritance – A class inherits from another derived class.
3. Hierarchical Inheritance – Multiple classes inherit from one parent.
4. Multiple Inheritance (via Interfaces) – A class implements multiple interfaces.

Note: Java does not support multiple inheritance with classes to avoid ambiguity.

Example:
class Parent {
void show() {
[Link]("This is the Parent class");
}
}

class Child extends Parent {


void display() {
[Link]("This is the Child class");
}
}

public class Main {


public static void main(String[] args) {
Child obj = new Child();
[Link](); // Output: This is the Parent class
[Link](); // Output: This is the Child class
}
}
Advantages: ✔ Promotes code reusability.
✔ Establishes a relationship between classes.

4. Polymorphism
Polymorphism allows a single method or operator to perform different behaviors based on the
context. There are two types:

1. Compile-time Polymorphism (Method Overloading)


2. Runtime Polymorphism (Method Overriding)

Method Overloading (Compile-time Polymorphism)

 Occurs in the same class.


 Same method name, different parameter lists.

class MathOperations {
int add(int a, int b) {
return a + b;
}

int add(int a, int b, int c) {


return a + b + c;
}
}

public class Main {


public static void main(String[] args) {
MathOperations obj = new MathOperations();
[Link]([Link](5, 10)); // Output: 15
[Link]([Link](5, 10, 15)); // Output: 30
}
}

Method Overriding (Runtime Polymorphism)

 Occurs in parent-child relationship (inheritance).


 Same method name, same parameters, different behavior.

class Animal {
void makeSound() {
[Link]("Animal makes a sound");
}
}

class Dog extends Animal {


@Override
void makeSound() {
[Link]("Dog barks");
}
}

public class Main {


public static void main(String[] args) {
Animal myDog = new Dog();
[Link](); // Output: Dog barks
}
}

Advantages: ✔ Improves code flexibility.


✔ Supports dynamic method resolution.

Additional OOP Features in Java


1. Classes and Objects

 Class: A blueprint for objects.


 Object: An instance of a class.

Example:

class Car {
String model;

void showModel() {
[Link]("Car Model: " + model);
}
}

public class Main {


public static void main(String[] args) {
Car c = new Car();
[Link] = "Tesla Model X";
[Link](); // Output: Car Model: Tesla Model X
}
}

2. Constructors

 Special methods that initialize objects.


 Types:
o Default Constructor
o Parameterized Constructor
o Copy Constructor (not built-in in Java)

Example:

class Person {
String name;

// Constructor
Person(String n) {
name = n;
}
void display() {
[Link]("Name: " + name);
}
}

public class Main {


public static void main(String[] args) {
Person p = new Person("Alice");
[Link](); // Output: Name: Alice
}
}

3. Interfaces vs. Abstract Classes

Feature Interface Abstract Class


Methods Only abstract methods Can have both abstract & concrete methods
Variables Public, static, final Can have any access modifier
Multiple Inheritance Yes No (Only single inheritance)
Usage Used for defining a contract Used for partial implementation

Conclusion
OOP in Java follows four key principles: Encapsulation, Abstraction, Inheritance, and
Polymorphism, which make code more modular, reusable, and maintainable. Understanding
these concepts is essential for writing efficient Java programs.

Would you like additional notes on a specific part of OOP?

Here are detailed notes on the features of Java:

Features of Java
Java is a high-level, object-oriented programming language that has been widely adopted for
building a variety of applications, from web-based systems to mobile apps. Java has several
key features that make it a popular choice for developers.

1. Simple
Java was designed to be easy to learn and use. It eliminates complex features of other
programming languages like C and C++ (such as pointers and memory management) to make
it more straightforward.

Key Points:

 No explicit pointer usage: Java handles memory management automatically using


garbage collection.
 No complex memory management: The programmer doesn’t have to manually
allocate and deallocate memory.
 Syntax similar to C/C++: Java’s syntax is simple and resembles C/C++, making it
easy for developers familiar with these languages to transition.

2. Object-Oriented
Java follows the principles of object-oriented programming (OOP). It is built around objects
and classes, which helps in structuring code in a way that it is reusable, scalable, and easier to
maintain.

Key Points:

 Classes and Objects: Everything in Java is an object, and classes serve as templates
for creating objects.
 Encapsulation, Inheritance, Polymorphism, and Abstraction: These four
fundamental OOP principles are integral parts of Java, enabling more efficient and
modular code design.

3. Platform-Independent (Write Once, Run Anywhere -


WORA)
One of the defining features of Java is its ability to run on any platform without needing to be
recompiled. This is due to the use of the Java Virtual Machine (JVM), which interprets
compiled Java code into platform-specific bytecode.

Key Points:

 Bytecode: When a Java program is compiled, it is converted into bytecode (not


machine code). The bytecode can be executed on any device that has a JVM.
 Cross-Platform Compatibility: Java programs can run on any device or operating
system that has a compatible JVM installed (e.g., Windows, Linux, MacOS).

4. Robust
Java is known for its robustness due to its strong memory management and exception-
handling features.

Key Points:
 Automatic Garbage Collection: Java handles memory management automatically by
using garbage collection to remove unused objects.
 Exception Handling: Java provides a powerful exception-handling mechanism that
helps in detecting and handling runtime errors effectively.
 Strong Typing: Java is a statically typed language, meaning type checking is done at
compile-time, reducing the chances of type-related errors at runtime.
 Memory Management: Java prevents memory leaks by automatically handling
memory allocation and deallocation.

5. Secure
Java provides several features to ensure the security of its programs and systems.

Key Points:

 Bytecode Verification: Before bytecode is executed, it is verified by the JVM to


ensure that it doesn’t contain harmful code.
 Security Manager: Java provides a security manager that controls access to system
resources like the file system and network.
 Cryptography: Java includes a built-in library (Java Cryptography Architecture -
JCA) that supports encryption, hashing, and other security protocols.

6. Multithreaded
Java supports multithreading, allowing multiple tasks to be executed simultaneously within a
program. This is particularly useful for creating interactive applications that require
simultaneous operations, like video games, real-time systems, and web servers.

Key Points:

 Concurrency: Java provides an integrated multithreading API that makes it easier to


manage threads and perform concurrent tasks.
 Thread Class and Runnable Interface: Java allows the creation of threads by
extending the Thread class or implementing the Runnable interface.

7. Distributed
Java is designed to be used in distributed computing environments. It provides features like
Remote Method Invocation (RMI), making it easy to write programs that can communicate
across a network.

Key Points:
 RMI (Remote Method Invocation): Enables objects to communicate with each other
on different machines across a network.
 JavaBeans: JavaBeans are reusable software components that can be manipulated
visually in a builder tool.
 Networking Support: Java provides extensive APIs to support networking
capabilities, including working with sockets and IP protocols.

8. High Performance
Java was initially considered slower than languages like C and C++ because of its interpreted
nature. However, with advancements like Just-In-Time (JIT) compilers and optimizations,
Java performance has significantly improved.

Key Points:

 JIT Compiler: The JIT compiler in Java converts bytecode into machine code at
runtime, which significantly boosts performance.
 Optimized JVM: The JVM performs various optimizations during execution to
ensure that Java applications run efficiently.

9. Portable
Java is highly portable due to its platform-independent nature and the fact that Java bytecode
can run on any platform with a compatible JVM. This makes Java an ideal choice for
developing cross-platform applications.

Key Points:

 Platform-Independent Bytecode: The same bytecode can run on different devices


and operating systems with the help of the JVM.
 No Dependency on Platform-Specific Details: Java programs don’t rely on
underlying platform-specific implementations, making them portable across diverse
systems.

10. Dynamic
Java is considered a dynamic language because it is capable of adapting to changing
environments, particularly at runtime. It supports dynamic method loading and runtime
polymorphism.

Key Points:
 Dynamic Class Loading: Java can load classes at runtime, which allows for the
creation of dynamic applications.
 Reflection API: The reflection API in Java allows programs to inspect and
manipulate the properties of objects at runtime.
 Garbage Collection: Java’s garbage collection mechanism operates dynamically,
freeing up memory space as needed without user intervention.

11. Multiplatform (Cross-Platform)


Java can run on various devices and platforms, making it a perfect candidate for mobile and
enterprise applications.

Key Points:

 Android Development: Java is the primary language used for Android app
development.
 Enterprise Systems: Java is widely used in enterprise-level applications and systems
due to its scalability and robustness.

12. Rich Standard Library


Java comes with a comprehensive set of libraries and APIs that cover everything from
networking to graphical user interfaces (GUIs) to database connectivity.

Key Points:

 Core Libraries: Java’s standard library includes APIs for input/output (I/O),
networking, collections, and much more.
 Frameworks: There are various frameworks built on top of Java, such as Spring,
Hibernate, and JavaFX, that help speed up the development process.

13. Architecture-Neutral
Java’s architecture-neutral feature allows it to run on any device or operating system with
minimal changes.

Key Points:

 Bytecode: The compilation of Java code into bytecode ensures that it can run on any
architecture, making it independent of hardware-specific details.
14. Easy to Learn
Java is considered one of the easiest programming languages to learn. It has a simple and
clear syntax, making it accessible to beginners.

Key Points:

 Readable Code: Java syntax is clean and readable, and it has a well-defined structure.
 Widely Taught: Java is a commonly taught language in computer science courses
and programming tutorials.

Conclusion
Java's combination of features such as simplicity, portability, security, and high performance
makes it a versatile and powerful language for developing a wide range of applications.
Whether you're building web-based applications, mobile apps, or enterprise systems, Java’s
features provide the flexibility and efficiency needed for modern software development.

Would you like further clarification or examples on any of these features?

Here’s a detailed comparison of Java and C++, highlighting the differences between the two
programming languages:

Java vs. C++


Java and C++ are both powerful, high-performance programming languages used for
developing a variety of applications, from system software to enterprise applications.
However, they differ significantly in several aspects, from syntax and memory management
to paradigms and design philosophies.

1. Language Paradigm
Java:

 Object-Oriented: Java is purely object-oriented, meaning everything in Java is


treated as an object (except for primitive data types).
 No Multiple Inheritance: Java does not support multiple inheritance through classes
but allows multiple inheritance through interfaces.
C++:

 Multi-Paradigm: C++ supports both procedural and object-oriented programming


paradigms. It is flexible, allowing developers to choose the best paradigm for their
application.
 Multiple Inheritance: C++ supports multiple inheritance, where a class can inherit
from multiple classes.

2. Memory Management
Java:

 Automatic Memory Management: Java uses automatic garbage collection to


manage memory. The garbage collector automatically frees up memory that is no
longer in use by the program, making memory management easier for the developer.
 No Pointers: Java does not allow direct memory manipulation via pointers, making it
safer than C++ in terms of memory management.

C++:

 Manual Memory Management: In C++, the programmer must manually allocate


and deallocate memory using new and delete keywords, which increases the risk of
memory leaks and errors.
 Pointers: C++ allows the use of pointers, which provide direct access to memory
addresses. This gives more control over memory but increases the complexity of the
code.

3. Compilation and Execution


Java:

 Compiled to Bytecode: Java code is first compiled to bytecode, which is platform-


independent. The bytecode can then be executed by the Java Virtual Machine
(JVM) on any system that has the JVM installed.
 WORA (Write Once, Run Anywhere): Java's platform-independent bytecode allows
it to run on any device or OS without modification, provided the JVM is available.

C++:

 Compiled to Machine Code: C++ code is compiled directly into machine code that is
specific to the operating system and hardware. This means C++ programs need to be
recompiled for different platforms.
 Platform Dependent: C++ is not platform-independent. The same C++ code may not
run on different operating systems without being recompiled or modified.
4. Exception Handling
Java:

 Strong Exception Handling: Java enforces exception handling. It has a robust


exception-handling mechanism using try, catch, finally, and throw to handle
errors.
 Checked and Unchecked Exceptions: Java distinguishes between checked
exceptions (which must be caught or declared) and unchecked exceptions (which are
runtime exceptions).

C++:

 Basic Exception Handling: C++ supports exception handling using try, catch, and
throw. However, exception handling in C++ is not as mandatory or integrated as in
Java.
 No Checked Exceptions: C++ does not distinguish between checked and unchecked
exceptions, leaving more responsibility to the developer to handle exceptions.

5. Syntax and Simplicity


Java:

 Simpler Syntax: Java’s syntax is simpler, with fewer ways to do the same thing. It is
more consistent and designed to avoid low-level programming tasks.
 No Operator Overloading: Java does not support operator overloading, making the
syntax more predictable and easier to understand.

C++:

 Complex Syntax: C++ has a more complex syntax with more features, which allows
greater flexibility but also increases the complexity of the language.
 Supports Operator Overloading: C++ allows operator overloading, enabling you to
define how operators (like +, -, etc.) work for custom data types.

6. Libraries and Standard APIs


Java:
 Large Standard Library: Java provides a rich and extensive standard library,
including libraries for GUI development (JavaFX), networking, I/O operations, and
more.
 Platform Independent APIs: Java's standard libraries are designed to work across all
platforms where Java is installed.

C++:

 Standard Template Library (STL): C++ offers the Standard Template Library
(STL), which provides powerful data structures like vectors, maps, and sets, along
with algorithms to manipulate them.
 Less Platform Independent: C++ libraries may require different implementations or
libraries depending on the platform.

7. Performance
Java:

 Slower Execution: Java typically executes slower than C++ because it runs on the
JVM. The interpretation of bytecode and the overhead of garbage collection can
reduce performance.
 JIT Compilation: Java uses Just-In-Time (JIT) compilation, which converts bytecode
to machine code at runtime, improving performance over time.

C++:

 Faster Execution: C++ tends to have better performance because it compiles directly
to machine code, which runs faster than bytecode.
 More Control over Performance: C++ allows more direct control over system
resources, enabling developers to optimize for performance, especially in memory-
intensive applications.

8. Portability
Java:

 Highly Portable: Due to the JVM and bytecode, Java programs are highly portable.
You can run the same Java code on any system with a compatible JVM without
modification.

C++:
 Less Portable: C++ programs are compiled directly to machine code, meaning they
are often dependent on the operating system and hardware, requiring recompilation
for different platforms.

9. Multi-threading
Java:

 Built-in Support for Multithreading: Java provides built-in support for


multithreading with the Thread class and the Runnable interface, making it easier to
develop multithreaded applications.
 Platform-Independent Multithreading: Java's multithreading model is implemented
in the JVM, making it platform-independent.

C++:

 Multithreading via Libraries: C++ provides multithreading support via libraries


such as POSIX threads (pthreads) or C++11 standard thread library. It does not have
built-in support as Java does.
 Platform Dependent: The threading model in C++ can be platform-dependent,
meaning programs might need adjustments based on the system.

10. GUI Development


Java:

 Cross-Platform GUI Libraries: Java provides libraries like Swing and JavaFX for
building platform-independent GUIs.
 Consistency: Java ensures that GUIs look and behave consistently across all
platforms.

C++:

 Platform-Specific GUI Libraries: C++ uses libraries like Qt or MFC (Microsoft


Foundation Classes) for GUI development, which may not be as portable across
different platforms.
 More Control: C++ provides more control over the system, allowing for custom-
designed GUI solutions.

11. Security
Java:
 Built-in Security Features: Java has built-in security features like bytecode
verification and runtime security checks, which ensure that malicious code cannot
harm the system.
 Security Manager: Java's Security Manager controls access to system resources and
can restrict certain operations like file access or network communication.

C++:

 Less Security by Default: C++ does not have the same built-in security mechanisms.
The responsibility for ensuring security lies with the developer.
 Manual Resource Management: C++ provides more control but also increases the
risk of bugs such as buffer overflows and memory leaks, which can lead to security
vulnerabilities.

Conclusion:
Feature Java C++
Multi-paradigm (Object-oriented +
Language Type Object-oriented (pure)
Procedural)
Memory Manual memory management
Automatic Garbage Collection
Management using new and delete
Compilation Compiled to bytecode, run on JVM Compiled directly to machine code
Single inheritance with interfaces
Inheritance Supports multiple inheritance
for multiple inheritance
Slower due to JVM and bytecode Faster as it compiles directly to
Performance
execution machine code
Exception Strong and enforced exception
More flexible, but not enforced
Handling handling
Write Once, Run Anywhere Platform-dependent, needs
Portability
(WORA) recompilation
External libraries or OS-specific
Multithreading Built-in support via Thread class
threads
Security is the developer's
Security Strong built-in security features
responsibility

Which to Choose?

 Java is ideal for cross-platform applications, web development, enterprise systems,


and mobile applications (especially Android).
 C++ is better for system-level programming, game development, performance-critical
applications, and applications that require direct hardware access.

Both languages have their strengths and ideal use cases, so your choice depends on your
specific requirements.

Data Types in Java


Java is a strongly typed programming language, meaning every variable must be declared
with a specific data type. Java provides primitive and non-primitive (reference) data types.
Understanding data types is crucial as they define the type of data a variable can store and the
operations that can be performed on them.

1. Categories of Data Types


Java data types are broadly classified into:

1. Primitive Data Types (Built-in, fundamental types)


2. Non-Primitive Data Types (Reference types like objects, arrays, and interfaces)

2. Primitive Data Types


Primitive data types store simple values and are not objects. They occupy fixed memory
space and operate at a lower level for better performance.

Default
Type Size Description
Value
byte 1 byte (8-bit) 0 Stores small integers (-128 to 127)
Stores medium-range integers (-32,768 to
short 2 bytes (16-bit) 0
32,767)
int 4 bytes (32-bit) 0 Stores whole numbers (-2³¹ to 2³¹-1)
long 8 bytes (64-bit) 0L Stores large whole numbers (-2⁶³ to 2⁶³-1)
Stores decimal numbers (single precision, ~7
float 4 bytes (32-bit) 0.0f
digits)
Stores decimal numbers (double precision, ~15
double 8 bytes (64-bit) 0.0d
digits)
char 2 bytes (16-bit) '\u0000' Stores a single character (Unicode)
1 bit (JVM
boolean false Stores true or false
dependent)

1.1 Integer Data Types

Used for storing whole numbers.

 byte: Useful for saving memory in large arrays.


 short: Used when memory is a concern but larger numbers are required.
 int: Default data type for integer values.
 long: Used when int is not sufficient (add L suffix: long num = 100000L;).

1.2 Floating-Point Data Types

Used for storing numbers with decimals.


 float: Smaller range, single-precision (must use f suffix: float num = 10.5f;).
 double: Larger range, double-precision (default for decimal values).

1.3 Character Data Type

 char: Stores a single character and supports Unicode.


 Example:
 char letter = 'A';
 char unicodeLetter = '\u0041'; // Unicode for 'A'

1.4 Boolean Data Type

 boolean: Can only store true or false.


 Example:
 boolean isJavaFun = true;
 boolean isCold = false;

3. Non-Primitive Data Types


Non-primitive (reference) data types store memory addresses of objects. They provide
flexibility to create complex data structures.

3.1 String

 A sequence of characters, implemented as an object.


 Example:
 String message = "Hello, Java!";

3.2 Arrays

 A collection of elements of the same type.


 Example:
 int[] numbers = {10, 20, 30, 40};

3.3 Classes and Objects

 Class: A blueprint for creating objects.


 Object: An instance of a class.
 Example:
 class Car {
 String model;
 int year;
 }

 Car myCar = new Car(); // Object creation

3.4 Interface

 A blueprint for classes that defines methods but does not implement them.
 Example:
 interface Animal {
 void makeSound();
 }

4. Type Conversion in Java


Java allows implicit and explicit type conversions.

4.1 Implicit Type Casting (Widening)

 Automatically converts a smaller type to a larger type.


 Example:
 int num = 100;
 double d = num; // Automatic conversion (int → double)

4.2 Explicit Type Casting (Narrowing)

 Requires manual conversion of a larger type to a smaller type.


 Example:
 double pi = 3.14;
 int intPi = (int) pi; // Explicit casting (double → int)

5. Wrapper Classes
Java provides wrapper classes to treat primitive data types as objects.

Primitive Wrapper Class


byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

Example:

int num = 10;


Integer objNum = [Link](num); // Boxing (primitive → object)
int newNum = [Link](); // Unboxing (object → primitive)

6. Default Values of Data Types


Type Default Value
byte 0
short 0
Type Default Value
int 0
long 0L
float 0.0f
double 0.0d
char '\u0000' (null)
boolean false
Object null

Conclusion
 Java provides 8 primitive data types for efficient memory usage and performance.
 Non-primitive types allow the creation of complex data structures like strings,
arrays, and objects.
 Type conversion helps in compatibility between different data types.
 Wrapper classes allow treating primitive types as objects when necessary.

Understanding data types is crucial for efficient Java programming and memory
management. 🚀

Control Statements in Java


Control statements in Java control the flow of execution in a program. They help in
decision-making, looping, and jumping from one part of the code to another.

Types of Control Statements


Java provides three main types of control statements:

1. Decision-Making Statements (Conditional)


o if, if-else, if-else-if
o switch
2. Looping Statements (Iteration)
o for, while, do-while
3. Jumping Statements
o break
o continue
o return

1. Decision-Making Statements (Conditional Statements)


These statements help execute different blocks of code based on conditions.
1.1 if Statement

Executes a block of code only if the condition is true.

Syntax:

if (condition) {
// Code to execute if condition is true
}

Example:

int age = 18;


if (age >= 18) {
[Link]("You are eligible to vote.");
}

1.2 if-else Statement

Executes one block if the condition is true and another block if it is false.

Syntax:

if (condition) {
// Executes if condition is true
} else {
// Executes if condition is false
}

Example:

int number = -5;


if (number > 0) {
[Link]("Positive Number");
} else {
[Link]("Negative Number");
}

1.3 if-else-if Ladder

Checks multiple conditions in sequence.

Syntax:

if (condition1) {
// Code for condition1
} else if (condition2) {
// Code for condition2
} else {
// Default block (if none of the conditions are true)
}
Example:

int marks = 85;


if (marks >= 90) {
[Link]("Grade: A");
} else if (marks >= 75) {
[Link]("Grade: B");
} else if (marks >= 50) {
[Link]("Grade: C");
} else {
[Link]("Fail");
}

1.4 switch Statement

 Used when multiple if-else conditions are needed.


 Compares a variable against multiple possible values.

Syntax:

switch (expression) {
case value1:
// Code for value1
break;
case value2:
// Code for value2
break;
default:
// Default block (if no case matches)
}

Example:

int day = 3;
switch (day) {
case 1:
[Link]("Monday");
break;
case 2:
[Link]("Tuesday");
break;
case 3:
[Link]("Wednesday");
break;
default:
[Link]("Invalid Day");
}

💡 Note: break prevents fall-through to the next case.

2. Looping Statements (Iteration)


Loops execute a block of code multiple times.

2.1 for Loop

Used when the number of iterations is known.

Syntax:

for (initialization; condition; update) {


// Code to be executed
}

Example:

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


[Link]("Iteration: " + i);
}

2.2 while Loop

Used when the number of iterations is unknown and depends on a condition.

Syntax:

while (condition) {
// Code to execute while condition is true
}

Example:

int count = 1;
while (count <= 5) {
[Link]("Count: " + count);
count++;
}

2.3 do-while Loop

Similar to while, but ensures the loop runs at least once before checking the condition.

Syntax:

do {
// Code to execute
} while (condition);

Example:

int num = 1;
do {
[Link]("Number: " + num);
num++;
} while (num <= 5);

💡 Difference between while and do-while:

 while checks the condition first, and then executes.


 do-while executes first, then checks the condition.

3. Jumping Statements
Used to control the flow by breaking loops or skipping iterations.

3.1 break Statement

Terminates the loop or switch statement.

Example:

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


if (i == 3) {
break; // Stops the loop when i == 3
}
[Link]("i: " + i);
}

Output:

i: 1
i: 2

3.2 continue Statement

Skips the current iteration and moves to the next.

Example:

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


if (i == 3) {
continue; // Skips iteration when i == 3
}
[Link]("i: " + i);
}

Output:

i: 1
i: 2
i: 4
i: 5
3.3 return Statement

Used to exit from a method and return a value.

Example:

public class Example {


public static int sum(int a, int b) {
return a + b; // Returns the sum
}

public static void main(String[] args) {


int result = sum(10, 20);
[Link]("Sum: " + result);
}
}

4. Difference Between break and continue


Feature break continue
Effect Stops the loop Skips the current iteration
Usage Used in loops and switch Used in loops only
Control Exits completely Moves to the next iteration

Conclusion
 Decision-making statements (if, switch) control program flow based on
conditions.
 Loops (for, while, do-while) allow repeated execution of code.
 Jumping statements (break, continue, return) alter loop execution.

Mastering control statements helps in writing efficient and optimized Java programs. 🚀

Identifiers in Java – Detailed Notes

Identifiers are names given to variables, methods, classes, packages,


and other program elements in Java.

1. Rules for Defining Identifiers


1. Allowed Characters:
o Can include letters (A-Z, a-z), digits (0-9), underscore
(_), and dollar sign ($).
Must start with a letter, underscore, or $ (cannot start
o
with a digit).
2. Case Sensitivity:
o age and Age are different identifiers.
3. No Keywords:
o Cannot use Java reserved keywords (e.g., int, class, public).
4. No Length Limit:
o Can be of any length, but keep it meaningful.
5. No Special Symbols:
o Cannot use @, #, %, &, etc.

2. Valid vs Invalid Identifiers


Valid Invalid Reason
age 1age Starts with a digit
_name @name Contains @
$salary class class is a keyword
firstNa first- Hyphen not
me name allowed

3. Naming Conventions (Best Practices)


Conventi
Type Example
on
Class/ Student, BankAccou
PascalCase
Interface nt
Method/ getName(), totalAm
camelCase
Variable ount
UPPER_CAS
Constant E
MAX_VALUE, PI
[Link]
Package lowercase
t

4. Examples of Identifiers
java
Copy
// Variables
int age = 25;
String firstName = "John";

// Methods
void calculateSalary() { ... }

// Classes
class Employee { ... }

// Constants
final double PI = 3.14;

5. Common Mistakes
❌ Using reserved keywords (int public = 10; → Error).
❌ Starting with a digit (2ndPlace → Invalid).
❌ Inconsistent naming (FirstName vs firstName).

Types of Identifiers
1. Variable Identifiers

Used to name variables.

java
CopyEdit
int age = 25;
String userName = "John";

2. Method Identifiers

Used for method names.

java
CopyEdit
void calculateTotal() {
[Link]("Calculating total...");
}

3. Class Identifiers

Used to name classes.

java
CopyEdit
class Student {
int rollNumber;
}

4. Constant Identifiers

 Constants are usually written in UPPER_CASE with underscores.

java
CopyEdit
final int MAX_SPEED = 120;
Best Practices for Naming Identifiers
✔ Use meaningful names (e.g., customerAge instead of x).
✔ Follow camelCase for variables and methods (e.g., studentName).
✔ Use PascalCase for class names (e.g., EmployeeDetails).
✔ Use underscores for constants (e.g., MAX_LIMIT).
✔ Avoid single-letter names unless for temporary variables (i, j in loops).

Arrays in Java
Introduction
An array in Java is a collection of elements of the same data type stored in contiguous
memory locations. It allows efficient data manipulation and retrieval.

Features of Arrays in Java


✅ Fixed Size: The size of an array is defined at the time of declaration and cannot be
changed.
✅ Zero-Based Indexing: The first element is at index 0, the second at index 1, and so on.
✅ Homogeneous Elements: All elements in an array must be of the same data type.
✅ Stored in Contiguous Memory: Elements are stored in a continuous block of memory for
fast access.
✅ Supports Multidimensional Arrays: Java allows 2D, 3D, and higher-dimensional arrays.

Declaring and Initializing an Array


1. Declaration of an Array
dataType[] arrayName; // Preferred
dataType arrayName[]; // Allowed (C-style)

Example:

int[] numbers; // Preferred


int numbers[]; // Also valid

2. Allocating Memory to an Array


arrayName = new dataType[size];

Example:
numbers = new int[5]; // Allocates memory for 5 integers

3. Declaration & Memory Allocation Together


int[] numbers = new int[5]; // Creates an integer array of size 5

4. Initializing an Array at Declaration


int[] numbers = {10, 20, 30, 40, 50}; // Array with predefined values

Accessing Array Elements


Array elements are accessed using their index (starting from 0).

int[] numbers = {10, 20, 30, 40, 50};


[Link](numbers[0]); // Output: 10
[Link](numbers[3]); // Output: 40

💡 Note: Accessing an index out of bounds (numbers[10] when size is 5) will result in:

Exception in thread "main" [Link]

Types of Arrays in Java


1. One-Dimensional Arrays
int[] arr = new int[3]; // Creating an array of size 3
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;

[Link](arr[1]); // Output: 20

2. Multi-Dimensional Arrays

Java allows 2D, 3D, and n-Dimensional arrays.

2D Array (Matrix)

int[][] matrix = {
{1, 2, 3},
{4, 5, 6}
};

[Link](matrix[1][2]); // Output: 6

Jagged Array (Different column sizes)

int[][] jagged = new int[3][];


jagged[0] = new int[2]; // Row 0 has 2 columns
jagged[1] = new int[3]; // Row 1 has 3 columns
jagged[2] = new int[1]; // Row 2 has 1 column

Array Operations
1. Traversing an Array (Using Loops)
int[] arr = {10, 20, 30, 40, 50};

// Using for loop


for (int i = 0; i < [Link]; i++) {
[Link](arr[i]);
}

// Using enhanced for loop


for (int num : arr) {
[Link](num);
}

2. Copying an Array

Method 1: Using Loop

int[] original = {1, 2, 3, 4, 5};


int[] copy = new int[[Link]];

for (int i = 0; i < [Link]; i++) {


copy[i] = original[i];
}

Method 2: Using [Link]()

int[] original = {1, 2, 3, 4, 5};


int[] copy = new int[[Link]];

[Link](original, 0, copy, 0, [Link]);

Method 3: Using [Link]()

int[] original = {1, 2, 3, 4, 5};


int[] copy = [Link](original, [Link]);

3. Sorting an Array

Using [Link]()

import [Link];

int[] numbers = {50, 20, 40, 10, 30};


[Link](numbers);
[Link]([Link](numbers)); // Output: [10, 20, 30, 40,
50]

4. Searching in an Array

Using Linear Search

int[] arr = {10, 20, 30, 40, 50};


int key = 30;
boolean found = false;

for (int num : arr) {


if (num == key) {
found = true;
break;
}
}

if (found) {
[Link]("Element found!");
} else {
[Link]("Element not found!");
}

Using Binary Search (Only for Sorted Arrays)

import [Link];

int[] arr = {10, 20, 30, 40, 50};


int key = 30;
int index = [Link](arr, key);

if (index >= 0) {
[Link]("Element found at index: " + index);
} else {
[Link]("Element not found!");
}

Array Class in Java ([Link])


Java provides utility methods through Arrays class:

Method Description
[Link](arr) Sorts the array in ascending order
[Link](arr, key) Searches for key in a sorted array
[Link](arr) Returns a string representation of the array
[Link](arr, length) Copies array with new length
[Link](arr, value) Fills array with a value

Example:

import [Link];
int[] numbers = {3, 1, 4, 1, 5};
[Link](numbers, 9);
[Link]([Link](numbers)); // Output: [9, 9, 9, 9, 9]

Difference Between Array and ArrayList


Feature Array ([]) ArrayList ([Link])
Size Fixed Dynamic (can grow/shrink)
Performance Fast (direct access) Slightly slower (dynamic resizing)
Type Safety Supports both primitives & objects Only supports objects
Methods No built-in methods Provides add(), remove(), get(), etc.

Conclusion
 Arrays provide a way to store multiple elements of the same type.
 Fixed in size and use zero-based indexing.
 Can be one-dimensional or multi-dimensional.
 Java provides utility methods in the Arrays class for sorting, searching, and copying.
 Use ArrayList for dynamic resizing instead of arrays.

Mastering arrays is essential for efficient data handling in Java programs! 🚀

Operators in Java
Introduction
Operators in Java are symbols that perform operations on variables and values. Java provides
a rich set of operators, which can be categorized based on their functionality.

Types of Operators in Java


Java operators are broadly classified into 8 categories:

1. Arithmetic Operators
2. Relational (Comparison) Operators
3. Logical Operators
4. Bitwise Operators
5. Assignment Operators
6. Unary Operators
7. Ternary (Conditional) Operator
8. Shift Operators
1. Arithmetic Operators
These operators perform mathematical operations like addition, subtraction, multiplication,
division, and modulus.

Operator Symbol Example (int a = 10, b = 5) Result


Addition + a + b 15
Subtraction - a - b 5
Multiplication * a * b 50
Division / a / b 2
Modulus % a % b 0 (Remainder)

🔹 Example Code:

public class ArithmeticExample {


public static void main(String[] args) {
int a = 10, b = 5;
[Link]("Addition: " + (a + b)); // 15
[Link]("Subtraction: " + (a - b)); // 5
[Link]("Multiplication: " + (a * b)); // 50
[Link]("Division: " + (a / b)); // 2
[Link]("Modulus: " + (a % b)); // 0
}
}

2. Relational (Comparison) Operators


These operators compare two values and return a boolean result (true or false).

Operator Symbol Example (a = 10, b = 5) Result


Equal to == a == b false
Not equal to != a != b true
Greater than > a > b true
Less than < a < b false
Greater than or equal to >= a >= b true
Less than or equal to <= a <= b false

🔹 Example Code:

public class ComparisonExample {


public static void main(String[] args) {
int a = 10, b = 5;
[Link](a > b); // true
[Link](a < b); // false
[Link](a == b); // false
[Link](a != b); // true
}
}
3. Logical Operators
Logical operators are used to perform boolean logic operations.

Operator Symbol Example (x = true, y = false) Result


AND && x && y false
OR ` `
NOT ! !x false

🔹 Example Code:

public class LogicalExample {


public static void main(String[] args) {
boolean x = true, y = false;
[Link](x && y); // false
[Link](x || y); // true
[Link](!x); // false
}
}

4. Bitwise Operators
These operators perform operations on individual bits of numbers.

Operator Symbol Example (a = 5, b = 3) Binary Representation Result


Bitwise AND & 5 & 3 0101 & 0011 → 0001 1
Bitwise OR ` ` `5 3`
Bitwise XOR ^ 5 ^ 3 0101 ^ 0011 → 0110 6
Bitwise Complement ~ ~5 ~0101 → 1010 -6

🔹 Example Code:

public class BitwiseExample {


public static void main(String[] args) {
int a = 5, b = 3;
[Link](a & b); // 1
[Link](a | b); // 7
[Link](a ^ b); // 6
[Link](~a); // -6
}
}

5. Assignment Operators
These operators assign values to variables.
Operator Example (x = 10) Equivalent to
= x = 10 Assign 10 to x
+= x += 5 x = x + 5
-= x -= 5 x = x - 5
*= x *= 5 x = x * 5
/= x /= 5 x = x / 5
%= x %= 5 x = x % 5

🔹 Example Code:

public class AssignmentExample {


public static void main(String[] args) {
int x = 10;
x += 5; // x = 15
[Link](x);
}
}

6. Unary Operators
These operators operate on a single operand.

Operator Symbol Example Result


Positive + +x 10
Negative - -x -10
Increment ++ ++x 11
Decrement -- --x 9

🔹 Example Code:

public class UnaryExample {


public static void main(String[] args) {
int x = 10;
[Link](++x); // 11 (Pre-increment)
[Link](x--); // 11 (Post-decrement)
}
}

7. Ternary Operator
The ternary operator (? :) is a shorthand for if-else.

🔹 Syntax:

variable = (condition) ? value_if_true : value_if_false;

🔹 Example:

public class TernaryExample {


public static void main(String[] args) {
int a = 10, b = 20;
int min = (a < b) ? a : b;
[Link]("Minimum: " + min);
}
}

8. Shift Operators
These operators shift bits left (<<) or right (>>).

Operator Example Result


Left Shift x << 2 x * 2^2
Right Shift x >> 2 x / 2^2

🔹 Example:

public class ShiftExample {


public static void main(String[] args) {
int x = 8;
[Link](x << 2); // 32
[Link](x >> 2); // 2
}
}

Conclusion
 Operators help in performing calculations, comparisons, logical operations, and bit
manipulations.
 Understanding Java operators is essential for efficient coding and problem-solving.
🚀

Classes in Java – Detailed Notes


Classes are the fundamental building blocks of object-oriented programming in Java. They
serve as blueprints for creating objects, encapsulating data (attributes) and behavior
(methods).

1. Class Components
A Java class consists of:
1. Fields (Member Variables) - Store object state
2. Methods - Define object behavior
3. Constructors - Special methods for object initialization
4. Blocks - Code blocks for initialization
5. Nested Classes/Interfaces - Inner classes/interfaces
java
Copy
public class Car {
// Fields
private String model;
private int year;

// Constructor
public Car(String model, int year) {
[Link] = model;
[Link] = year;
}

// Method
public void startEngine() {
[Link]("Engine started!");
}
}

2. Class Declaration Syntax


java
Copy
[access-modifier] [non-access-modifiers] class ClassName {
// Class body
}
Example:
java
Copy
public final class Student extends Person implements Serializable {
// Class implementation
}

3. Access Modifiers

Modifie
Visibility
r

public Accessible from anywhere

protected Accessible within package and subclasses

(default) Accessible within package only

private Accessible within class only

4. Constructors
Special methods called when creating objects:
4.1 Default Constructor
java
Copy
public class Book {
public Book() { } // Default constructor
}
4.2 Parameterized Constructor
java
Copy
public class Book {
private String title;

public Book(String title) {


[Link] = title;
}
}
4.3 Constructor Overloading
java
Copy
public class Book {
private String title;
private String author;

public Book(String title) {


this(title, "Unknown");
}

public Book(String title, String author) {


[Link] = title;
[Link] = author;
}
}

5. Methods
5.1 Method Structure
java
Copy
[access-modifier] [non-access-modifiers] return-type methodName([parameters]) {
// Method body
[return statement]
}
Example:
java
Copy
public double calculateArea(double radius) {
return [Link] * radius * radius;
}
5.2 Method Overloading
Same name, different parameters:
java
Copy
public void print(int num) { ... }
public void print(String text) { ... }
public void print(double num) { ... }

6. Static Members
Belong to the class rather than instances:
java
Copy
public class Counter {
static int count = 0; // Static variable

public Counter() {
count++;
}

public static void printCount() { // Static method


[Link]("Count: " + count);
}
}
Usage:
java
Copy
[Link](); // Called without creating instance

7. this Keyword
Refers to current object instance:
 Access instance variables shadowed by parameters
 Call one constructor from another
 Pass current object as parameter
java
Copy
public class Person {
private String name;

public Person(String name) {


[Link] = name; // Differentiates instance var from parameter
}
}

8. final Keyword
 final class: Cannot be extended
 final method: Cannot be overridden
 final variable: Cannot be reassigned
java
Copy
public final class Constants {
public static final double PI = 3.14159;
}

9. Object Creation
java
Copy
ClassName objectName = new ClassName([arguments]);
Example:
java
Copy
Car myCar = new Car("Toyota", 2020);
[Link]();

10. Best Practices


✔ Follow naming conventions (PascalCase for class names)
✔ Encapsulate fields (make private, provide getters/setters)
✔ Keep classes focused (Single Responsibility Principle)
✔ Use proper access modifiers
✔ Document classes with Javadoc comments

java
Copy
/**
* Represents a bank account with basic operations
*/
public class BankAccount {
private double balance;

public void deposit(double amount) { ... }


public void withdraw(double amount) { ... }
}

11. Common Mistakes


❌ Forgetting new keyword when creating objects
❌ Not initializing object fields properly
❌ Making everything public (breaking encapsulation)
❌ Creating overly large classes
❌ Confusing static and instance members
Constructors in Java
Introduction
A constructor in Java is a special type of method that is used to initialize objects. It is
automatically called when an object of a class is created. The main purpose of a constructor is
to assign initial values to the instance variables of the class.

1. Characteristics of Constructors
 Same name as the class.
 No return type (not even void).
 Called automatically when an object is created.
 Used to initialize object properties.
 Can be overloaded (multiple constructors with different parameters).
 If no constructor is defined, Java provides a default constructor.

2. Types of Constructors
(i) Default Constructor (No-Argument Constructor)

 Does not accept any parameters.


 Automatically provided if no constructor is explicitly defined.
 Initializes variables with default values (0, null, or false).

🔹 Example:

class Student {
String name;
int age;

// Default Constructor
Student() {
[Link]("Default Constructor called!");
name = "Unknown";
age = 18;
}

void display() {
[Link]("Name: " + name + ", Age: " + age);
}
}

public class Main {


public static void main(String[] args) {
Student s1 = new Student(); // Calls the default constructor
[Link]();
}
}

Output:

Default Constructor called!


Name: Unknown, Age: 18

(ii) Parameterized Constructor

 Accepts arguments to initialize object properties.


 Allows setting initial values dynamically at object creation.

🔹 Example:

class Student {
String name;
int age;

// Parameterized Constructor
Student(String n, int a) {
name = n;
age = a;
}

void display() {
[Link]("Name: " + name + ", Age: " + age);
}
}

public class Main {


public static void main(String[] args) {
Student s1 = new Student("Alice", 20);
Student s2 = new Student("Bob", 22);
[Link]();
[Link]();
}
}

Output:

Name: Alice, Age: 20


Name: Bob, Age: 22

(iii) Copy Constructor

 Creates a new object by copying values from another object.


 Java does not provide a built-in copy constructor like C++, but we can
implement it manually.

🔹 Example:

class Student {
String name;
int age;

// Parameterized Constructor
Student(String n, int a) {
name = n;
age = a;
}

// Copy Constructor
Student(Student s) {
name = [Link];
age = [Link];
}

void display() {
[Link]("Name: " + name + ", Age: " + age);
}
}

public class Main {


public static void main(String[] args) {
Student s1 = new Student("Alice", 20);
Student s2 = new Student(s1); // Copy constructor
[Link]();
[Link]();
}
}

Output:

Name: Alice, Age: 20


Name: Alice, Age: 20

3. Constructor Overloading
 Multiple constructors in the same class with different parameters.
 The correct constructor is chosen based on the arguments provided during
object creation.

🔹 Example:

class Student {
String name;
int age;

// Default Constructor
Student() {
name = "Unknown";
age = 18;
}

// Parameterized Constructor
Student(String n) {
name = n;
age = 18;
}

// Another Parameterized Constructor


Student(String n, int a) {
name = n;
age = a;
}

void display() {
[Link]("Name: " + name + ", Age: " + age);
}
}

public class Main {


public static void main(String[] args) {
Student s1 = new Student();
Student s2 = new Student("Alice");
Student s3 = new Student("Bob", 22);

[Link]();
[Link]();
[Link]();
}
}

Output:

Name: Unknown, Age: 18


Name: Alice, Age: 18
Name: Bob, Age: 22

4. Constructor with this Keyword


 Used to refer to the current class instance variables.
 Can be used to call another constructor within the same class.

🔹 Example (Using this to initialize variables):

class Student {
String name;
int age;

// Constructor using 'this'


Student(String name, int age) {
[Link] = name;
[Link] = age;
}

void display() {
[Link]("Name: " + name + ", Age: " + age);
}
}

public class Main {


public static void main(String[] args) {
Student s1 = new Student("Alice", 20);
[Link]();
}
}

Output:

Name: Alice, Age: 20

🔹 Example (Calling another constructor using this())

class Student {
String name;
int age;

// Default Constructor
Student() {
this("Unknown", 18); // Calls the parameterized constructor
}

// Parameterized Constructor
Student(String name, int age) {
[Link] = name;
[Link] = age;
}

void display() {
[Link]("Name: " + name + ", Age: " + age);
}
}

public class Main {


public static void main(String[] args) {
Student s1 = new Student(); // Calls default constructor, which
calls parameterized constructor
[Link]();
}
}

Output:

Name: Unknown, Age: 18

5. Difference Between Constructor and Method


Feature Constructor Method
Purpose Initializes an object Performs an operation
Name Same as class name Can have any name
Return Type No return type (not even void) Must have a return type
Called automatically when an Called explicitly using
Call Mechanism
object is created [Link]()
Overloading Yes Yes
Default Provided by Java if not explicitly
Not provided by Java
Implementation defined
6. Final Notes
✔ Constructors are essential for initializing objects.
✔ They improve code reusability by setting default values or dynamic values.
✔ Overloading allows different ways to initialize an object.
✔ Copy constructors help in duplicating object data.
✔ The this keyword helps in differentiating instance variables from parameters.

super() Call

 Calls parent class constructor


 Must be first statement (if used)
 Added automatically if not specified
java
Copy
public class Vehicle {
private int wheels;

public Vehicle(int wheels) {


[Link] = wheels;
}
}

public class Car extends Vehicle {


private String model;

public Car(int wheels, String model) {


super(wheels); // Calls Vehicle constructor
[Link] = model;
}
}

Inheritance in Java
Introduction
Inheritance is one of the fundamental concepts of Object-Oriented Programming (OOP)
in Java. It allows a class (called the child/subclass) to acquire the properties and behaviors of
another class (called the parent/superclass).

Key Features of Inheritance:

✅ Code Reusability – Avoids rewriting code by using the properties of an existing class.
✅ Method Overriding – A child class can provide a specific implementation of a method
inherited from the parent.
✅ Extends Keyword – The extends keyword is used to define inheritance.
1. Types of Inheritance in Java
Java supports different types of inheritance:

1️⃣ Single Inheritance


2️⃣ Multilevel Inheritance
3️⃣ Hierarchical Inheritance
4️⃣ Hybrid Inheritance (Achieved via Interfaces)
❌ Multiple Inheritance (Not supported with classes, but possible using interfaces)

2. Syntax of Inheritance
To create a subclass, we use the extends keyword:

class Parent {
// Parent class members
}

class Child extends Parent {


// Child class members
}

3. Types of Inheritance in Detail


(i) Single Inheritance

 A child class inherits from a single parent class.

🔹 Example:

class Animal { // Parent class


void eat() {
[Link]("This animal eats food.");
}
}

class Dog extends Animal { // Child class


void bark() {
[Link]("The dog barks.");
}
}

public class Main {


public static void main(String[] args) {
Dog d = new Dog();
[Link](); // Inherited method
[Link](); // Own method
}
}

Output:

This animal eats food.


The dog barks.

(ii) Multilevel Inheritance

 A class is derived from another derived class, forming a chain.

🔹 Example:

class Animal {
void eat() {
[Link]("This animal eats food.");
}
}

class Mammal extends Animal {


void walk() {
[Link]("Mammals can walk.");
}
}

class Dog extends Mammal {


void bark() {
[Link]("The dog barks.");
}
}

public class Main {


public static void main(String[] args) {
Dog d = new Dog();
[Link](); // From Animal
[Link](); // From Mammal
[Link](); // Own method
}
}

Output:

This animal eats food.


Mammals can walk.
The dog barks.

(iii) Hierarchical Inheritance

 A single parent class is inherited by multiple child classes.

🔹 Example:

class Animal {
void eat() {
[Link]("This animal eats food.");
}
}

class Dog extends Animal {


void bark() {
[Link]("The dog barks.");
}
}

class Cat extends Animal {


void meow() {
[Link]("The cat meows.");
}
}

public class Main {


public static void main(String[] args) {
Dog d = new Dog();
[Link]();
[Link]();

Cat c = new Cat();


[Link]();
[Link]();
}
}

Output:

This animal eats food.


The dog barks.
This animal eats food.
The cat meows.

(iv) Hybrid Inheritance (Using Interfaces)

Java does not support multiple inheritance with classes to avoid ambiguity. However, it
can be achieved using interfaces.

🔹 Example:

interface Animal {
void eat();
}

interface Sound {
void makeSound();
}

class Dog implements Animal, Sound {


public void eat() {
[Link]("Dog eats food.");
}

public void makeSound() {


[Link]("Dog barks.");
}
}

public class Main {


public static void main(String[] args) {
Dog d = new Dog();
[Link]();
[Link]();
}
}

Output:

Dog eats food.


Dog barks.

4. Super Keyword in Inheritance


 super is used to refer to the immediate parent class.
 It helps in calling parent class methods, constructors, and variables.

Using super to call the Parent Class Constructor


class Animal {
Animal() {
[Link]("Animal constructor called.");
}
}

class Dog extends Animal {


Dog() {
super(); // Calls parent class constructor
[Link]("Dog constructor called.");
}
}

public class Main {


public static void main(String[] args) {
Dog d = new Dog();
}
}

Output:

Animal constructor called.


Dog constructor called.

5. Method Overriding in Inheritance


 Allows a subclass to provide a specific implementation of an inherited method.
 The method signature must be the same in both parent and child classes.
 The @Override annotation is used to indicate that a method is overridden.

🔹 Example:

class Animal {
void makeSound() {
[Link]("Animal makes a sound.");
}
}

class Dog extends Animal {


@Override
void makeSound() {
[Link]("Dog barks.");
}
}

public class Main {


public static void main(String[] args) {
Dog d = new Dog();
[Link](); // Calls overridden method
}
}

Output:

Dog barks.

6. Final Keyword in Inheritance


 final prevents inheritance or method overriding.
 A final class cannot be extended.
 A final method cannot be overridden.

🔹 Example:

final class Animal {


void sound() {
[Link]("Animal makes a sound.");
}
}

// Error: Cannot inherit from final class


// class Dog extends Animal { }

public class Main {


public static void main(String[] args) {
Animal a = new Animal();
[Link]();
}
}

7. Difference Between Inheritance and Interface


Feature Inheritance (extends) Interface (implements)
Methods can be inherited Methods are only declared (until Java
Method Implementation
and overridden 8)
Supports Multiple
❌ Not supported ✅ Supported
Inheritance
Used for extending an Used for achieving multiple
Use Case
existing class inheritance and abstraction
Keyword extends implements

8. Summary
✔ Inheritance allows code reuse and hierarchy representation.
✔ Types: Single, Multilevel, Hierarchical, Hybrid (via Interfaces).
✔ The super keyword is used to call parent class methods or constructors.
✔ Method overriding allows modifying inherited methods.
✔ Final classes/methods cannot be extended or overridden.
✔ Java does not support multiple inheritance with classes, but interfaces can be used.

Would you like notes on any other topic related to Java Programming? 🚀

Multilevel Inheritance in Java


Introduction
🔹 Multilevel Inheritance is a type of inheritance where a class (child) inherits from another
derived class (parent), which itself is inherited from another class (grandparent). This forms a
chain of inheritance where properties and methods are passed down through multiple levels.

Key Characteristics
✅ Code Reusability – Common features are inherited across multiple levels.
✅ Hierarchy Structure – Parent, Child, and Grandchild relationship.
✅ Method Overriding – Allows subclasses to redefine parent class methods.
✅ Use of super Keyword – Access parent class methods and constructors.

Syntax of Multilevel Inheritance


// Grandparent Class
class A {
void methodA() {
[Link]("Method from Class A");
}
}

// Parent Class
class B extends A {
void methodB() {
[Link]("Method from Class B");
}
}

// Child Class
class C extends B {
void methodC() {
[Link]("Method from Class C");
}
}

public class Main {


public static void main(String[] args) {
C obj = new C();
[Link](); // Inherited from A
[Link](); // Inherited from B
[Link](); // Defined in C
}
}
Output:
Method from Class A
Method from Class B
Method from Class C
✔ Class C inherits from Class B, which in turn inherits from Class A.
✔ The object of Class C can access methods from all three classes.

Example: Real-Life Implementation


Vehicle Inheritance
class Vehicle {
void start() {
[Link]("Vehicle is starting...");
}
}

class Car extends Vehicle {


void accelerate() {
[Link]("Car is accelerating...");
}
}

class SportsCar extends Car {


void turboMode() {
[Link]("Turbo mode activated!");
}
}

public class Main {


public static void main(String[] args) {
SportsCar sc = new SportsCar();
[Link](); // From Vehicle
[Link](); // From Car
[Link](); // From SportsCar
}
}
Output:
Vehicle is starting...
Car is accelerating...
Turbo mode activated!

Method Overriding in Multilevel Inheritance


🔹 Overriding allows a subclass to redefine a method from its superclass.
🔹 The @Override annotation helps prevent mistakes.

Example: Method Overriding


class Animal {
void sound() {
[Link]("Animals make sounds");
}
}

class Mammal extends Animal {


@Override
void sound() {
[Link]("Mammals make specific sounds");
}
}

class Dog extends Mammal {


@Override
void sound() {
[Link]("Dog barks");
}
}

public class Main {


public static void main(String[] args) {
Dog dog = new Dog();
[Link](); // Calls the overridden method in Dog class
}
}
Output:
Dog barks
✔ The method sound() is overridden at each level.
✔ The most specific method (Dog class) is executed.

Use of super Keyword


🔹 super is used to call:

1. Parent class constructors


2. Parent class methods
Example: Using super
class Parent {
Parent() {
[Link]("Parent class constructor");
}

void display() {
[Link]("Parent class method");
}
}

class Child extends Parent {


Child() {
super(); // Calls Parent constructor
[Link]("Child class constructor");
}

void display() {
[Link](); // Calls Parent method
[Link]("Child class method");
}
}

public class Main {


public static void main(String[] args) {
Child obj = new Child();
[Link]();
}
}
Output:
Parent class constructor
Child class constructor
Parent class method
Child class method
✔ super(); ensures the parent constructor runs first.
✔ [Link](); calls the parent class method before executing the child's method.

Advantages of Multilevel Inheritance


✔ Code Reusability – Avoids redundancy, making code cleaner.
✔ Organized Structure – Defines relationships between classes clearly.
✔ Method Overriding – Enhances flexibility by modifying inherited methods.

Disadvantages of Multilevel Inheritance


❌ Complexity – Debugging multiple levels of inheritance is difficult.
❌ Performance Overhead – Multiple calls to parent classes can slow execution.
❌ Tight Coupling – Changes in the base class affect all derived classes.

Comparison: Single vs. Multilevel vs. Hierarchical Inheritance

Single Hierarchical
Feature Multilevel Inheritance
Inheritance Inheritance

1 (Parent → 2+ (Parent → Child → 1 Parent, Multiple


Levels
Child) Grandchild) Children

Code
Limited High High
Reusability

Complexity Low Moderate Moderate

Example A→B A→B→C A → (B, C, D)

Conclusion
✔ Multilevel Inheritance allows a class to inherit from a derived class, forming a
hierarchy.
✔ It provides code reusability, structure, and method overriding benefits.
✔ However, deep inheritance chains can increase complexity and tight coupling.

Would you like practice questions or real-world case studies on this topic? 🚀

Hierarchical Inheritance in Java


Introduction
Hierarchical Inheritance is a type of inheritance in Java where a single parent class has
multiple child classes. Each child class inherits the properties and behaviors of the parent
class, but each can also have its own specific attributes or methods. Unlike multilevel
inheritance, where a class is inherited from another derived class in a chain, in hierarchical
inheritance, all child classes share the same parent class but do not inherit from each other.
Key Characteristics of Hierarchical Inheritance
✅ Single Parent Class – One parent class is shared by multiple child classes.
✅ Code Reusability – Child classes can reuse the code of the parent class.
✅ Different Behaviors – Each child class can have different methods and properties.
✅ Method Overriding – Child classes can override parent class methods.

Syntax of Hierarchical Inheritance


class Parent {
void methodParent() {
[Link]("Method from Parent class");
}
}

class Child1 extends Parent {


void methodChild1() {
[Link]("Method from Child1 class");
}
}

class Child2 extends Parent {


void methodChild2() {
[Link]("Method from Child2 class");
}
}

public class Main {


public static void main(String[] args) {
Child1 obj1 = new Child1();
[Link](); // Inherited from Parent
obj1.methodChild1(); // Specific to Child1

Child2 obj2 = new Child2();


[Link](); // Inherited from Parent
obj2.methodChild2(); // Specific to Child2
}
}

Output:
Method from Parent class
Method from Child1 class
Method from Parent class
Method from Child2 class

✔ Both Child1 and Child2 share the same Parent class and inherit its methods.
✔ Each child class has its own specific methods (methodChild1 and methodChild2).
Real-World Example: Animal Hierarchy
Example: Animal Inheritance
class Animal {
void eat() {
[Link]("Animals need food to survive");
}
}

class Dog extends Animal {


void bark() {
[Link]("Dog barks");
}
}

class Cat extends Animal {


void meow() {
[Link]("Cat meows");
}
}

class Elephant extends Animal {


void trumpet() {
[Link]("Elephant trumpets");
}
}

public class Main {


public static void main(String[] args) {
Dog dog = new Dog();
[Link](); // Inherited from Animal
[Link](); // Specific to Dog

Cat cat = new Cat();


[Link](); // Inherited from Animal
[Link](); // Specific to Cat

Elephant ele = new Elephant();


[Link](); // Inherited from Animal
[Link](); // Specific to Elephant
}
}

Output:
Animals need food to survive
Dog barks
Animals need food to survive
Cat meows
Animals need food to survive
Elephant trumpets

✔ All child classes (Dog, Cat, Elephant) share the eat() method from the Animal class.
✔ Each child class has its own specific behavior (bark(), meow(), trumpet()).
Method Overriding in Hierarchical Inheritance
In Hierarchical Inheritance, child classes can override the methods of the parent class to
provide specific implementations. This is useful when the behavior of the inherited method
needs to be changed or customized.

Example: Method Overriding in Hierarchical Inheritance


class Animal {
void sound() {
[Link]("Animals make sounds");
}
}

class Dog extends Animal {


@Override
void sound() {
[Link]("Dog barks");
}
}

class Cat extends Animal {


@Override
void sound() {
[Link]("Cat meows");
}
}

public class Main {


public static void main(String[] args) {
Animal myDog = new Dog();
[Link](); // Dog's overridden method

Animal myCat = new Cat();


[Link](); // Cat's overridden method
}
}

Output:
Dog barks
Cat meows

✔ Dog and Cat have overridden the sound() method from the Animal class.
✔ The most specific version of the method is executed based on the object type (Dog or Cat).

Advantages of Hierarchical Inheritance


✔ Code Reusability – Child classes reuse methods and properties from the parent class.
✔ Better Structure – Helps organize the program logically by categorizing different types of
classes under a common parent.
✔ Ease of Maintenance – Common functionalities are centralized in the parent class,
making it easier to update and maintain the code.
✔ Polymorphism – Provides flexibility by allowing objects of child classes to be treated as
objects of the parent class.

Disadvantages of Hierarchical Inheritance


❌ Tight Coupling – Child classes depend on the parent class. Changes in the parent class can
affect all child classes.
❌ Ambiguity – In case of multiple inheritance (which is not allowed in Java), ambiguity
arises when a method is inherited from more than one class.
❌ Increased Complexity – More classes can lead to increased complexity and difficulty in
debugging.

Comparison: Hierarchical vs. Multilevel Inheritance


Feature Hierarchical Inheritance Multilevel Inheritance
Number of Child Multiple child classes inherit
One child inherits from another child
Classes from a single parent
High, as multiple classes share
Code Reusability High, but in a chain-like structure
the same parent
Can be more complex, especially in
Complexity Moderate, easier to follow
deep inheritance chains
Example Parent → Child1, Child2 Parent → Child → Grandchild

Conclusion
✔ Hierarchical Inheritance allows a single parent class to be shared by multiple child
classes.
✔ It promotes code reusability, simplifies code structure, and can reduce redundancy.
✔ However, changes in the parent class can affect all child classes, leading to tight coupling.

Would you like more examples or a few practice problems to solidify your understanding of
hierarchical inheritance? 🚀

Method Overriding in Java


Introduction
Method Overriding is a feature in Java that allows a subclass to provide a specific
implementation of a method that is already defined in its superclass. The overridden method
in the subclass must have the same name, return type, and parameter list as the method in the
superclass. Method overriding is used to define specific behaviors of inherited methods in a
subclass.

Key Points of Method Overriding


1. Same Method Signature: The method in the subclass must have the same name,
return type, and parameters as the method in the superclass.
2. Runtime Polymorphism: Method overriding is a way to achieve runtime
polymorphism, where the method that gets executed depends on the object type, not
the reference type.
3. Use of @Override Annotation: The @Override annotation is used to indicate that a
method is overriding a method in its superclass. It helps to avoid errors like
mismatched method signatures.
4. Access Modifiers: The access level of the overriding method cannot be more
restrictive than the method being overridden.
5. Constructor and Static Methods: Constructors and static methods cannot be
overridden.

Syntax of Method Overriding


class Parent {
void display() {
[Link]("Display method from Parent class");
}
}

class Child extends Parent {


@Override
void display() {
[Link]("Display method from Child class");
}
}

public class Main {


public static void main(String[] args) {
Parent obj = new Child();
[Link](); // Calls overridden method in Child class
}
}

Output:
Display method from Child class

✔ Explanation: Even though the reference type is Parent, the object created is of type
Child. Therefore, the display() method from the Child class is executed.
Real-Life Example: Shape Hierarchy
Consider a scenario with a parent class Shape and two child classes Circle and Rectangle.
Both subclasses override the area() method to provide specific implementations for
calculating the area.

Example: Method Overriding


class Shape {
// Method in Parent class
double area() {
[Link]("Area of Shape");
return 0;
}
}

class Circle extends Shape {


double radius;

Circle(double radius) {
[Link] = radius;
}

@Override
double area() {
return [Link] * radius * radius; // Overriden method
}
}

class Rectangle extends Shape {


double length, width;

Rectangle(double length, double width) {


[Link] = length;
[Link] = width;
}

@Override
double area() {
return length * width; // Overriden method
}
}

public class Main {


public static void main(String[] args) {
Shape shape = new Shape();
[Link]("Area of Shape: " + [Link]()); // Parent
class method

Shape circle = new Circle(5); // Child class Circle


[Link]("Area of Circle: " + [Link]()); //
Circle's overridden method

Shape rectangle = new Rectangle(4, 6); // Child class Rectangle


[Link]("Area of Rectangle: " + [Link]()); //
Rectangle's overridden method
}
}
Output:
Area of Shape: 0.0
Area of Circle: 78.53981633974483
Area of Rectangle: 24.0

✔ Explanation:

 The Shape class provides a basic area() method.


 The Circle and Rectangle classes override the area() method to calculate the area
specific to their shapes.
 When we create objects of Circle and Rectangle, their respective area() methods
are called, showcasing runtime polymorphism.

Method Overriding Rules


1. Same Signature: The overriding method must have the same method signature
(name, return type, and parameters).
2. Return Type: The return type of the overridden method can be the same or a subtype
(covariant return type). For example, if the superclass method returns Object, the
subclass method can return String (since String is a subclass of Object).
3. Access Modifiers: The overriding method can have the same or more permissive
access level than the method in the parent class. For example:
o If the parent method is public, the child method can be public or
protected, but not private.
o If the parent method is protected, the child method can be protected or
public.
4. Constructor and Static Methods: Constructors cannot be overridden, and static
methods can be hidden but not overridden. Static methods are bound to the class, and
method overriding applies only to instance methods.
5. Final Methods: A method declared final cannot be overridden.
6. Abstract Methods: If a parent class has an abstract method, the child class must
override it.

Runtime Polymorphism (Dynamic Method Dispatch)


Method overriding allows for runtime polymorphism, meaning the method that gets called
is determined at runtime based on the object type, not the reference type.

Example: Runtime Polymorphism


class Animal {
void sound() {
[Link]("Animals make sounds");
}
}
class Dog extends Animal {
@Override
void sound() {
[Link]("Dog barks");
}
}

class Cat extends Animal {


@Override
void sound() {
[Link]("Cat meows");
}
}

public class Main {


public static void main(String[] args) {
Animal myAnimal = new Animal();
[Link](); // Calls method in Animal class

Animal myDog = new Dog();


[Link](); // Calls overridden method in Dog class

Animal myCat = new Cat();


[Link](); // Calls overridden method in Cat class
}
}

Output:
Animals make sounds
Dog barks
Cat meows

✔ Explanation: Even though the references are of type Animal, the actual object type (Dog
or Cat) determines which sound() method is called at runtime.

Advantages of Method Overriding


1. Runtime Polymorphism – Allows different classes to provide specific
implementations of a method.
2. Code Reusability – Subclasses can reuse the code of the parent class but provide
specific behavior when needed.
3. Flexibility – The child class can modify the behavior of the parent class method to
suit its needs.

Disadvantages of Method Overriding


1. Complexity – Overriding methods can add complexity, especially when working with
a large number of classes.
2. Performance Overhead – Runtime polymorphism can cause slight performance
overhead as method resolution happens at runtime.

Conclusion
Method overriding is a fundamental concept in Java that supports runtime polymorphism
and allows subclasses to define specific behaviors for methods inherited from their
superclass. It is a key feature in object-oriented programming for achieving dynamic method
dispatch and increasing the flexibility of the code.

Would you like more examples, practice questions, or a deeper dive into specific cases of
method overriding? 🚀

Abstract Classes in Java


Introduction
An abstract class in Java is a class that cannot be instantiated on its own and is designed to
be inherited by other classes. It serves as a blueprint for subclasses. An abstract class may
have abstract methods (methods without a body) as well as concrete methods (methods with a
body). It allows you to define methods that must be implemented by the subclasses while also
providing default implementations that can be inherited.

Key Points of Abstract Classes


1. Abstract Methods: An abstract class can contain abstract methods. These are
methods that have no implementation in the abstract class, and the subclasses are
required to implement them.
2. Concrete Methods: Abstract classes can also have concrete methods with full
implementation, which can be inherited or overridden by subclasses.
3. Cannot Be Instantiated: You cannot create an object of an abstract class directly. It
must be extended by a concrete class.
4. Subclass Implementation: Any class that extends an abstract class must either
implement all the abstract methods or be declared abstract itself.
5. Use of abstract Keyword: The keyword abstract is used to declare a class or
method as abstract.
6. Constructor: Abstract classes can have constructors, which are called when an
instance of a subclass is created.

Syntax of Abstract Class


abstract class Parent {
abstract void display(); // Abstract method

void show() { // Concrete method


[Link]("This is a concrete method.");
}
}

class Child extends Parent {


@Override
void display() {
[Link]("Display method implemented in Child class.");
}
}

public class Main {


public static void main(String[] args) {
// Parent obj = new Parent(); // Error: Cannot instantiate abstract
class
Child childObj = new Child();
[Link](); // Calls overridden method in Child
[Link](); // Inherited concrete method from Parent
}
}

Output:
Display method implemented in Child class.
This is a concrete method.

Abstract Class with Abstract and Concrete Methods


An abstract class can have both abstract and concrete methods. Concrete methods are
inherited by subclasses without needing to be overridden, while abstract methods must be
implemented by subclasses.

Example: Abstract Class with Both Types of Methods


abstract class Animal {
abstract void sound(); // Abstract method

void eat() { // Concrete method


[Link]("Animals need food to survive");
}
}

class Dog extends Animal {


@Override
void sound() {
[Link]("Dog barks");
}
}

class Cat extends Animal {


@Override
void sound() {
[Link]("Cat meows");
}
}

public class Main {


public static void main(String[] args) {
Animal myDog = new Dog();
[Link](); // Calls Dog's sound()
[Link](); // Inherited method from Animal

Animal myCat = new Cat();


[Link](); // Calls Cat's sound()
[Link](); // Inherited method from Animal
}
}

Output:
Dog barks
Animals need food to survive
Cat meows
Animals need food to survive

✔ Explanation:

 The abstract method sound() is implemented by the Dog and Cat subclasses.
 The concrete method eat() is inherited directly from the Animal class without
modification.

When to Use Abstract Classes?


 Defining Common Template: When you want to define a common template for a
group of related classes, but you don’t want to instantiate the base class.
 Enforcing Method Implementation: When you want to enforce that certain methods
must be implemented in the subclasses, but also allow some methods to be inherited.
 Partial Implementation: When the base class can provide a partial implementation
that can be reused or modified in the subclasses.

Abstract Class vs Interface


While both abstract classes and interfaces are used to define common methods that must be
implemented by subclasses or implementing classes, they have key differences:

Feature Abstract Class Interface


Abstract Can have abstract and concrete Can only have abstract methods (until
Methods methods Java 8, which allows default methods)
Multiple A class can extend only one A class can implement multiple
Inheritance abstract class interfaces
Feature Abstract Class Interface
Constructor Can have constructors Cannot have constructors
Methods can have any access
Access
modifier (public, protected, Methods are implicitly public
Modifiers
private)
Field Variables Can have instance variables Can have only static and final variables

Example: Abstract Class vs Interface


Abstract Class Example
abstract class Animal {
abstract void sound(); // Abstract method

void eat() { // Concrete method


[Link]("Animal is eating");
}
}

class Dog extends Animal {


@Override
void sound() {
[Link]("Dog barks");
}
}

public class Main {


public static void main(String[] args) {
Animal dog = new Dog();
[Link]();
[Link]();
}
}

Interface Example
interface Animal {
void sound(); // Abstract method

default void eat() { // Default method in interface (Java 8+)


[Link]("Animal is eating");
}
}

class Dog implements Animal {


@Override
public void sound() {
[Link]("Dog barks");
}
}

public class Main {


public static void main(String[] args) {
Animal dog = new Dog();
[Link]();
[Link]();
}
}

Advantages of Abstract Classes


1. Partial Implementation: Allows partial implementation and code reusability.
2. Common Base for All Subclasses: Provides a common base for all subclasses to
inherit shared functionality.
3. Enforces Consistency: Ensures subclasses implement specific methods (abstract
methods).

Disadvantages of Abstract Classes


1. Single Inheritance Limitation: A class can inherit only one abstract class, which can
limit flexibility.
2. Cannot Instantiate: Abstract classes cannot be instantiated, which may be
inconvenient in some situations.

Conclusion
An abstract class is a blueprint for other classes, allowing you to define methods that must
be implemented in subclasses while providing some common behavior. It is particularly
useful for defining a common interface for related classes while allowing for shared or
specific functionality. It promotes code reuse and enforces consistency across classes.

Would you like to explore more about abstract classes through practice problems or real-
world scenarios?

Final Classes in Java


Introduction
In Java, a final class is a class that cannot be subclassed. This means no other class can
extend a final class. The keyword final is used to declare a class as final. Once a class is
marked as final, it is "locked" from inheritance. This can be useful in scenarios where you
want to ensure that the behavior of a class cannot be modified by subclassing.

Key Points of Final Classes


1. Cannot Be Inherited: A final class cannot be extended by any other class.
2. Preventing Modification: It is used to prevent the modification of a class's behavior
by subclassing.
3. Performance Improvement: The use of final classes can sometimes improve
performance because the Java compiler can optimize the code, knowing that the class
cannot be subclassed.
4. Final Methods: In addition to final classes, methods can also be declared final to
prevent overriding.

Syntax of a Final Class


final class Animal {
void sound() {
[Link]("Animal makes sound");
}
}

class Dog extends Animal { // Error: Cannot subclass a final class


void sound() {
[Link]("Dog barks");
}
}

Error Message:
Error: Cannot inherit from final 'Animal'

✔ Explanation: The Animal class is declared as final, so it cannot be subclassed by the Dog
class or any other class.

When to Use Final Classes?


1. To Provide Security: Final classes can be used to create immutable objects (like the
String class) or to prevent subclassing of critical classes.
2. To Prevent Modification: When you want to ensure that the behavior of a class is
not altered by subclassing, you can make the class final.
3. To Avoid Inheritance: If inheritance is not necessary for a class, making it final can
avoid unnecessary subclassing.

Example of Final Class


final class Vehicle {
void start() {
[Link]("Vehicle started");
}
}

public class Main {


public static void main(String[] args) {
Vehicle car = new Vehicle();
[Link](); // Calls method in Vehicle class
}
}

Output:
Vehicle started

✔ Explanation: The Vehicle class is final, meaning it cannot be subclassed. We can still
create objects of the Vehicle class and use its methods.

Difference Between Final Class and Final Methods


 Final Class: A class declared as final cannot be subclassed.
 Final Method: A method declared as final cannot be overridden by subclasses.

Example: Final Method


class Animal {
final void sound() { // final method
[Link]("Animal makes sound");
}
}

class Dog extends Animal {


@Override
void sound() { // Error: Cannot override final method
[Link]("Dog barks");
}
}

Error Message:
Error: Cannot override the final method from Animal

✔ Explanation: The sound() method in the Animal class is declared as final, so it cannot
be overridden by the Dog class.

Advantages of Final Classes


1. Security: Final classes help protect the integrity of a class’s behavior by preventing
subclassing and modification.
2. Performance Optimization: The Java compiler can optimize final classes since it
knows they cannot be extended.
3. Simplicity: It simplifies the design by preventing unnecessary or unauthorized
inheritance.

Disadvantages of Final Classes


1. Lack of Extensibility: The major disadvantage is that you cannot extend the
functionality of a final class through inheritance.
2. Reduced Flexibility: It may reduce flexibility in some cases, especially if you later
decide that subclassing would be beneficial.

Real-Life Example: String Class


The String class in Java is a final class, meaning it cannot be subclassed. This decision is
made to ensure the immutability and security of strings in Java.

Example: Final String Class


final class StringExample {
final String name = "Java";

void display() {
[Link]("Name: " + name);
}
}

public class Main {


public static void main(String[] args) {
StringExample example = new StringExample();
[Link](); // Displays: Name: Java
}
}

Output:
Name: Java

✔ Explanation: The StringExample class is final and cannot be extended by any other
class. Also, the name variable is a final variable, meaning it cannot be reassigned after its
initialization.

Conclusion
A final class is one that cannot be subclassed, providing a way to lock the behavior of a class
to prevent modification by inheritance. It is particularly useful in creating secure, immutable,
and optimized classes. However, it can reduce flexibility since you cannot extend a final
class.

Would you like to explore real-world use cases of final classes, or practice examples for
final methods and final variables?

String Class in Java


Introduction
The String class in Java is one of the most commonly used classes. It represents a sequence
of characters and is part of the [Link] package. Strings are immutable, meaning once a
String object is created, its value cannot be changed. The immutability of String makes it
thread-safe and more secure, as it cannot be modified after it is created.

Key Features of the String Class:

1. Immutable: Once a String object is created, its value cannot be changed. Any
modification to a string creates a new String object.
2. Final Class: The String class is declared as final, meaning it cannot be subclassed.
3. Constant Pool: Java uses a string constant pool for strings. When a string is created,
it checks if the string already exists in the pool. If it does, the existing reference is
reused; otherwise, a new string object is created.

Creating a String Object


In Java, strings can be created in two ways:

1. Using String Literal: When you create a string using a literal, the string is
automatically stored in the string constant pool.
2. Using the new Keyword: When you create a string using the new keyword, a new
string object is created in the heap memory.

Syntax:
String str1 = "Hello"; // String literal (stored in string pool)
String str2 = new String("Hello"); // String object created in heap

String Pool
Java maintains a pool of strings in memory, known as the String Constant Pool. When you
create a string using a string literal, it checks the pool to see if the string already exists. If it
does, the existing reference is used; if it doesn't, a new string is added to the pool.

Example: String Pool


public class Main {
public static void main(String[] args) {
String str1 = "Java";
String str2 = "Java"; // This refers to the same object in the
string pool

// Check if both references point to the same object


[Link](str1 == str2); // Output: true
}
}

Output:
true

✔ Explanation: Since str1 and str2 are referring to the same string in the string pool, the
result is true.

Important Methods of the String Class


1. Length

Returns the length of the string (i.e., the number of characters in the string).

String str = "Java";


int length = [Link](); // Returns 4

2. charAt(int index)

Returns the character at the specified index.

String str = "Java";


char ch = [Link](2); // Returns 'v'

3. substring(int start) and substring(int start, int end)

Returns a substring of the original string starting from the given index to the end (or up to a
specified end index).

String str = "Java Programming";


String subStr1 = [Link](5); // Returns "Programming"
String subStr2 = [Link](0, 4); // Returns "Java"

4. equals(Object obj)
Compares the content of two strings. Returns true if the strings are equal, otherwise returns
false.

String str1 = "Java";


String str2 = "java";
boolean isEqual = [Link](str2); // Returns false (case-sensitive)

5. equalsIgnoreCase(String anotherString)

Compares two strings, ignoring case differences.

String str1 = "JAVA";


String str2 = "java";
boolean isEqual = [Link](str2); // Returns true

6. toLowerCase() and toUpperCase()

Converts the string to lower case or upper case.

String str = "Java";


String lower = [Link](); // "java"
String upper = [Link](); // "JAVA"

7. contains(CharSequence sequence)

Checks if a given sequence of characters exists within the string.

String str = "Java Programming";


boolean contains = [Link]("Pro"); // Returns true

8. replace(char oldChar, char newChar)

Replaces all occurrences of a specified character with a new character.

String str = "Java Programming";


String newStr = [Link]('a', 'o'); // "Jovo Progromming"

9. trim()

Removes any leading and trailing whitespace from the string.

String str = " Java ";


String trimmed = [Link](); // "Java"

10. split(String regex)

Splits the string into an array of substrings based on the given delimiter (regular expression).

String str = "Java,Python,C++";


String[] languages = [Link](","); // {"Java", "Python", "C++"}

11. indexOf(String str)


Returns the index of the first occurrence of the specified substring.

String str = "Java Programming";


int index = [Link]("Pro"); // Returns 5

12. valueOf(Object obj)

Converts the object to its string representation.

int number = 100;


String str = [Link](number); // "100"

String Immutability
Strings in Java are immutable, meaning their values cannot be changed once they are created.
This is why operations like substring(), replace(), etc., do not modify the original string
but instead return a new string.

Example of Immutability
String str = "Hello";
[Link](" World"); // Does not modify 'str'
[Link](str); // Output: "Hello"

Explanation:

The concat() method creates a new string, but str still refers to the original string. To store
the new value, you would need to assign the result back to a string variable.

str = [Link](" World"); // Now 'str' is "Hello World"

StringBuffer and StringBuilder


Although String is immutable, if you need to frequently modify the string (like appending,
deleting, or inserting characters), it is more efficient to use StringBuffer or
StringBuilder. Both are mutable versions of String and offer faster performance when
you are making repeated modifications.

 StringBuffer: Synchronized, thread-safe.


 StringBuilder: Not synchronized, more efficient for single-threaded environments.

Example: StringBuilder
StringBuilder sb = new StringBuilder("Java");
[Link](" Programming");
[Link]([Link]()); // Output: "Java Programming"
Advantages of Using String Class
1. Memory Efficiency: The string constant pool reduces memory consumption for
string literals.
2. Security: Immutability makes strings more secure, as their values cannot be changed
after creation.
3. Convenience: The String class provides a rich set of methods for manipulating text,
making string handling easier.

Conclusion
The String class is a core class in Java that provides numerous methods for string
manipulation. Understanding how strings are managed in Java, such as their immutability and
the string constant pool, is important for writing efficient and secure Java applications.

Would you like to explore real-world scenarios where the String class is frequently used,
or do you have specific examples you want to work through?

Various Types of String Operations in Java


Java provides a variety of operations that can be performed on strings. These operations can
be used for string manipulation, such as modifying, comparing, searching, splitting, and
more. Below are the most common types of string operations in Java, categorized based on
their functionality.

1. String Creation Operations


Using String Literals
String str1 = "Hello"; // String literal

Using the new Keyword


String str2 = new String("Hello");

2. String Manipulation Operations


Concatenation (concat(), + operator)

Combines two strings into a single string.


 Using + Operator:

String str1 = "Hello";


String str2 = "World";
String result = str1 + " " + str2; // "Hello World"

 Using concat() Method:

String str1 = "Hello";


String str2 = "World";
String result = [Link](" ").concat(str2); // "Hello World"

Replace (replace())

Replaces all occurrences of a specified character or substring with another.

String str = "Java Programming";


String newStr = [Link]('a', 'o'); // "Jovo Progromming"

To Uppercase/Lowercase (toUpperCase(), toLowerCase())

Converts a string to all uppercase or lowercase letters.

String str = "Java";


String upper = [Link](); // "JAVA"
String lower = [Link](); // "java"

3. String Search Operations


indexOf()

Returns the index of the first occurrence of a specified substring or character.

String str = "Java Programming";


int index = [Link]("Pro"); // 5

lastIndexOf()

Returns the index of the last occurrence of a specified character or substring.

String str = "Java Programming Java";


int index = [Link]("Java"); // 17

contains()

Checks if a given sequence of characters exists within the string.

String str = "Java Programming";


boolean contains = [Link]("Pro"); // true
matches()

Checks if the string matches a given regular expression.

String str = "Java123";


boolean matches = [Link](".*\\d.*"); // true (matches if it contains
digits)

4. String Comparison Operations


equals()

Compares two strings for equality (case-sensitive).

String str1 = "Java";


String str2 = "Java";
boolean isEqual = [Link](str2); // true

equalsIgnoreCase()

Compares two strings for equality (ignoring case differences).

String str1 = "java";


String str2 = "JAVA";
boolean isEqual = [Link](str2); // true

compareTo()

Compares two strings lexicographically (returns a negative integer, zero, or a positive


integer).

String str1 = "Java";


String str2 = "JavaScript";
int result = [Link](str2); // Negative value (-3)

5. String Extraction Operations


substring()

Extracts a portion of the string starting from the specified index, or between two specified
indices.

String str = "Java Programming";


String subStr1 = [Link](5); // "Programming"
String subStr2 = [Link](0, 4); // "Java"

charAt()

Returns the character at a specified index.


String str = "Java";
char ch = [Link](2); // 'v'

split()

Splits the string into an array of substrings based on a delimiter (regular expression).

String str = "Java,Python,C++";


String[] languages = [Link](","); // {"Java", "Python", "C++"}

6. String Trimming Operations


trim()

Removes leading and trailing whitespace from the string.

String str = " Java ";


String trimmed = [Link](); // "Java"

7. String Transformation Operations


replaceAll()

Replaces each substring that matches a given regular expression with a new string.

String str = "Java 123 Java";


String result = [Link]("\\d", "#"); // "Java ### Java"

replaceFirst()

Replaces the first substring that matches the given regular expression.

String str = "Java Java Java";


String result = [Link]("Java", "Python"); // "Python Java Java"

8. String Case Operations


toLowerCase()

Converts all characters in the string to lowercase.

String str = "Java Programming";


String lower = [Link](); // "java programming"

toUpperCase()
Converts all characters in the string to uppercase.

String str = "Java Programming";


String upper = [Link](); // "JAVA PROGRAMMING"

9. String Padding Operations


[Link]()

Formats the string with specified placeholders, similar to the printf() method.

String formattedStr = [Link]("Hello %s, your balance is $%.2f",


"Alice", 125.75);
[Link](formattedStr); // "Hello Alice, your balance is
$125.75"

10. String Conversion Operations


valueOf()

Converts different types (like integers, floats, etc.) to their string representation.

int number = 100;


String str = [Link](number); // "100"

toString()

Converts any object to its string representation.

Object obj = 123;


String str = [Link](); // "123"

11. String Equality Operations


compareToIgnoreCase()

Compares two strings lexicographically, ignoring case differences.

String str1 = "java";


String str2 = "Java";
int result = [Link](str2); // 0 (equal ignoring case)

regionMatches()

Compares a substring of two strings, optionally ignoring case differences.

String str1 = "Java Programming";


String str2 = "java programming";
boolean result = [Link](true, 0, str2, 0, 4); // true (case-
insensitive)

12. String Validation Operations


isEmpty()

Checks whether the string is empty (length 0).

String str = "";


boolean isEmpty = [Link](); // true

isBlank()

Checks if the string is blank (only contains whitespace characters).

String str = " ";


boolean isBlank = [Link](); // true

Conclusion
Java provides a comprehensive set of operations to work with strings, which are immutable
objects. These operations allow you to manipulate, compare, extract, and format strings
efficiently. Understanding these operations is crucial for performing various tasks, from
simple string manipulation to more complex string handling in real-world applications.

Would you like to dive deeper into any specific string operation or see more advanced
examples of string manipulations?

Run-Time Polymorphism in Java


Introduction to Polymorphism
Polymorphism is a core concept in Object-Oriented Programming (OOP). It allows a single
entity (such as a method or an object) to take multiple forms. In Java, polymorphism is
primarily classified into two types:

1. Compile-Time Polymorphism (Method Overloading)


2. Run-Time Polymorphism (Method Overriding)

Focus: Run-Time Polymorphism

Run-time polymorphism, also known as dynamic method dispatch, is a feature in Java


where a method call to an overridden method is resolved at runtime. It occurs when a
subclass overrides a method of its superclass and the method that is called is determined by
the object being referred to at runtime.

In run-time polymorphism, the decision of which method to call is made at runtime based
on the actual object (not the reference type) that invokes the method.

Key Characteristics of Run-Time Polymorphism:

1. Method Overriding: It is achieved through method overriding, where a subclass


provides its specific implementation of a method that is already defined in its
superclass.
2. Dynamic Dispatch: The JVM (Java Virtual Machine) dynamically binds the method
call to the correct method at runtime based on the object’s actual type.
3. Upcasting: A reference variable of a superclass type is used to refer to an object of
the subclass type. This is called upcasting, and it allows the invocation of overridden
methods based on the actual object type.

How Run-Time Polymorphism Works


1. Method Overriding: A method in a subclass overrides a method in the superclass
with the same signature (same method name, return type, and parameters).
2. Upcasting: The superclass reference variable holds the subclass object.
3. Dynamic Method Dispatch: When the method is called on the superclass reference,
Java uses the actual object type to resolve the method to call at runtime, not the
reference type.

Example of Run-Time Polymorphism in Java


Superclass (Animal)
class Animal {
// Method to be overridden
void sound() {
[Link]("Animals make sounds");
}
}

Subclass (Dog)
class Dog extends Animal {
// Method overriding
@Override
void sound() {
[Link]("Dog barks");
}
}
Subclass (Cat)
class Cat extends Animal {
// Method overriding
@Override
void sound() {
[Link]("Cat meows");
}
}

Main Class
public class Main {
public static void main(String[] args) {
// Upcasting: Animal reference to Dog object
Animal animal1 = new Dog();
[Link](); // Output: Dog barks

// Upcasting: Animal reference to Cat object


Animal animal2 = new Cat();
[Link](); // Output: Cat meows
}
}

Explanation:

1. In the Main class, we create two objects: animal1 (which is of type Animal but points
to a Dog object) and animal2 (which is of type Animal but points to a Cat object).
2. The method sound() is overridden in both Dog and Cat classes.
3. Upcasting allows us to use the Animal reference to point to objects of Dog and Cat
types.
4. At runtime, the Java Virtual Machine (JVM) dynamically decides which method to
call based on the actual type of the object (not the reference type).
o When [Link]() is called, the method in the Dog class is invoked.
o When [Link]() is called, the method in the Cat class is invoked.

Key Points to Remember:


1. Upcasting is required for run-time polymorphism: A superclass reference variable
points to a subclass object.
2. Method Overriding: The method in the subclass must have the same method
signature as the one in the superclass.
3. The JVM determines at runtime which method to call, based on the actual object
type (not the reference type).
4. Overloaded methods are not polymorphic, as method overloading is resolved at
compile time.
Advantages of Run-Time Polymorphism
1. Flexibility: It allows for more flexible and extensible code. New classes can be added
without modifying existing code, as new methods can be created in subclasses.
2. Reusability: It promotes code reuse by allowing subclasses to provide their own
implementation of methods without changing the interface provided by the superclass.
3. Loose Coupling: The client code is not dependent on the specific class type, which
makes the system easier to maintain and extend.

Real-World Example of Run-Time Polymorphism


Let’s consider an example from a banking system, where we have different types of accounts
(SavingsAccount and CurrentAccount), each with its own interest calculation method.

Superclass (Account)
abstract class Account {
abstract void calculateInterest();
}

Subclass (SavingsAccount)
class SavingsAccount extends Account {
@Override
void calculateInterest() {
[Link]("Calculating interest for Savings Account.");
}
}

Subclass (CurrentAccount)
class CurrentAccount extends Account {
@Override
void calculateInterest() {
[Link]("Calculating interest for Current Account.");
}
}

Main Class
public class BankApp {
public static void main(String[] args) {
Account account1 = new SavingsAccount();
Account account2 = new CurrentAccount();

[Link](); // Output: Calculating interest for


Savings Account.
[Link](); // Output: Calculating interest for
Current Account.
}
}
Explanation:

 In the BankApp class, the superclass Account has an abstract method


calculateInterest().
 SavingsAccount and CurrentAccount override this method.
 At runtime, the appropriate calculateInterest() method is called based on the
type of object (either SavingsAccount or CurrentAccount), demonstrating run-time
polymorphism.

Conclusion
Run-time polymorphism (dynamic method dispatch) is a powerful concept in Java that
enables you to write flexible and maintainable code. By overriding methods in subclasses and
using superclass references, Java allows you to dynamically decide which method to call
based on the actual object type at runtime.

MODULE – 2

Packages in Java
A package in Java is a namespace that organizes classes and interfaces. It helps to avoid
name conflicts and makes it easier to manage large applications by grouping related classes
together.

1. Defining a Package
A package is defined using the package keyword at the beginning of a Java file.

Syntax
package package_name;

 The package_name should be unique and usually follows the domain name
convention in reverse ([Link]).
 All classes inside this file will belong to this package.

Example: Creating a Package


package mypackage; // Declaring package

public class MyClass {


public void display() {
[Link]("Hello from MyClass in mypackage!");
}
}
 The class MyClass now belongs to the mypackage package.

2. Implementing a Package
To implement a package, follow these steps:

1. Create a Directory Structure


o Package names should match the folder structure.
o If the package name is mypackage, create a folder named mypackage.
2. Save the Class in the Appropriate Folder
o Save the Java file inside the respective package directory.
o Example: If the file [Link] belongs to mypackage, save it inside the
mypackage folder.
3. Compile the Class with the -d Flag
o The -d option tells the compiler to create the package folder structure if it
doesn’t exist.
4. javac -d . [Link]
o The . means the package will be created in the current directory.
5. Run the Class from Outside the Package
o To run the compiled class:
6. java [Link]

3. Importing a Package
Once a package is defined, it can be imported and used in other Java programs.

3.1 Importing a Single Class


import [Link];

public class Test {


public static void main(String[] args) {
MyClass obj = new MyClass(); // Creating an object of MyClass
[Link]();
}
}

3.2 Importing All Classes from a Package

If a package contains multiple classes, we can import all of them using *:

import mypackage.*;

public class Test {


public static void main(String[] args) {
MyClass obj = new MyClass();
[Link]();
}
}

 The * imports all classes from the package but not sub-packages.

4. Access Modifiers and Packages


 public classes can be accessed from outside the package if imported.
 default (no modifier) classes are accessible only within the same package.
 Private members are not accessible outside their class, even if the class is imported.
 Protected members can be accessed in a subclass even if the subclass is in a different
package.

5. Using Built-in Java Packages


Java has many built-in packages, such as:

 [Link] – Utility classes like ArrayList, Scanner, etc.


 [Link] – Input and output operations.
 [Link] – Networking-related classes.

Example: Importing Java's Utility Package


import [Link]; // Importing built-in package

public class InputExample {


public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Enter a number: ");
int num = [Link]();
[Link]("You entered: " + num);
}
}

6. Sub-Packages
A package can have sub-packages for better organization.

Example: Creating a Sub-Package


package [Link];

public class SubClass {


public void show() {
[Link]("Inside SubClass of subpackage");
}
}
 This class is now part of [Link].

To import:

import [Link];

public class Test {


public static void main(String[] args) {
SubClass obj = new SubClass();
[Link]();
}
}

7. Static Import
Static members of a class can be imported directly using import static, allowing us to use
them without the class name.

Example: Static Import


import static [Link].*; // Importing all static members of Math

public class MathExample {


public static void main(String[] args) {
[Link](sqrt(16)); // No need to write [Link]()
[Link](pow(2, 3)); // No need to write [Link]()
}
}

Key Takeaways
 Packages help organize classes and avoid name conflicts.
 To create a package, use package package_name; at the top of the Java file.
 To compile a package, use javac -d . [Link].
 To use a package, import it with import package_name.ClassName; or import
package_name.*;.
 Access modifiers control package-level accessibility (public, protected,
default, private).
 Built-in packages like [Link], [Link], and [Link] provide useful classes.
 Sub-packages help in better structuring large projects.
 Static import allows direct access to static members of a class.

Would you like me to add example programs or explanations on any specific part? 😊

Interfaces in Java: Functional Interfaces


1. What is a Functional Interface?
A Functional Interface in Java is an interface that contains exactly one abstract method. It
may have multiple default or static methods, but only one abstract method makes it a
functional interface.

Functional interfaces enable the use of lambda expressions and method references, making
Java code more concise and readable.

Syntax
@FunctionalInterface
interface MyFunctionalInterface {
void abstractMethod(); // Only one abstract method
}

Even without the @FunctionalInterface annotation, an interface with a single abstract


method is still considered a functional interface. However, using this annotation helps ensure
it stays functional by preventing additional abstract methods.

2. Built-in Functional Interfaces in Java


Java provides several built-in functional interfaces in the [Link] package:

Functional Interface Abstract Method Description


Runnable void run() Represents a task to be executed on a thread.
Callable<T> T call() Similar to Runnable, but returns a result.
Supplier<T> T get() Provides results without taking input.
Consumer<T> void accept(T t) Accepts input but returns no output.
Function<T, R> R apply(T t) Takes one argument and returns a result.
Predicate<T> boolean test(T t) Evaluates a condition and returns true or false.

3. Creating and Using a Custom Functional Interface


Example 1: Functional Interface with Lambda Expression
@FunctionalInterface
interface MyInterface {
void showMessage(String message);
}

public class FunctionalInterfaceExample {


public static void main(String[] args) {
// Using Lambda Expression
MyInterface obj = message -> [Link]("Message: " +
message);
[Link]("Hello, Functional Interface!");
}
}

Explanation:

 The interface MyInterface has one abstract method showMessage().


 A lambda expression (message -> [Link](message)) is assigned to
obj, providing an implementation for showMessage().
 When [Link]("Hello") is called, it executes the lambda expression.

4. Built-in Functional Interfaces in Action


Example 2: Using Predicate<T> Functional Interface
import [Link];

public class PredicateExample {


public static void main(String[] args) {
Predicate<Integer> isEven = num -> num % 2 == 0;

[Link]([Link](10)); // true
[Link]([Link](15)); // false
}
}

Explanation:

 Predicate<T> has a method test(T t) that returns a boolean value.


 The lambda expression num -> num % 2 == 0 checks if a number is even.

Example 3: Using Function<T, R> Functional Interface


import [Link];

public class FunctionExample {


public static void main(String[] args) {
Function<Integer, String> converter = num -> "Number: " + num;

[Link]([Link](5)); // Number: 5
}
}

Explanation:

 Function<T, R> takes an input of type T and returns a result of type R.


 The lambda expression converts an integer to a formatted string.
Example 4: Using Consumer<T> Functional Interface
import [Link];

public class ConsumerExample {


public static void main(String[] args) {
Consumer<String> printMessage = msg -> [Link]("Message:
" + msg);

[Link]("Java is fun!"); // Message: Java is fun!


}
}

Explanation:

 Consumer<T> takes an input and performs an operation but does not return anything.
 The lambda expression prints the given message.

Example 5: Using Supplier<T> Functional Interface


import [Link];

public class SupplierExample {


public static void main(String[] args) {
Supplier<Double> randomValue = () -> [Link]();

[Link]([Link]()); // Random value


}
}

Explanation:

 Supplier<T> does not take input but returns a result when called.
 The lambda expression generates a random number.

5. Method References in Functional Interfaces


A method reference is a shortcut for writing lambda expressions when a method already
exists that matches the required method signature.

Example 6: Using Method Reference


@FunctionalInterface
interface MyPrinter {
void print(String message);
}

public class MethodReferenceExample {


public static void show(String msg) {
[Link]("Printing: " + msg);
}

public static void main(String[] args) {


MyPrinter printer = MethodReferenceExample::show;
[Link]("Hello, World!");
}
}

Explanation:

 Instead of using msg -> show(msg), we use MethodReferenceExample::show.


 The method reference directly points to an existing method.

6. Functional Interfaces vs Abstract Classes


Feature Functional Interface Abstract Class
Can have multiple abstract
Number of Methods Only one abstract method
methods
Default/Static
Can have default and static methods Can have regular methods
Methods
State (Instance
No instance variables Can have instance variables
Variables)
Supports functional programming (can Does not support functional
Multiple Inheritance
be used with lambdas) programming

7. Summary
 A Functional Interface has only one abstract method.
 It can have multiple default and static methods.
 The @FunctionalInterface annotation ensures no extra methods are added.
 Functional interfaces enable Lambda Expressions and Method References.
 Java provides built-in functional interfaces in [Link].
 Functional interfaces help make code concise, readable, and efficient.

This should give you a complete understanding of Functional Interfaces in Java! Let me
know if you need more details or examples. 😊

Lambda Expressions in Java


1. Introduction to Lambda Expressions
A Lambda Expression in Java is a short block of code that takes in parameters and returns a
value. It provides a concise and functional way of writing anonymous functions and is
primarily used to implement functional interfaces.

Lambda expressions were introduced in Java 8 to support functional programming and


make the code more readable and expressive.

2. Syntax of a Lambda Expression


Basic Syntax
(parameter1, parameter2, ...) -> { // Function body }

 ->is the lambda operator.


 The left side specifies parameters.
 The right side contains the function body.

Example: Lambda Expression to Print a Message


() -> [Link]("Hello, Lambda!");

 This is a simple lambda that takes no parameters and prints a message.

3. Why Use Lambda Expressions?


 Reduces boilerplate code: No need to define separate classes for functional
interfaces.
 Enhances readability: Short and clean syntax.
 Improves performance: Efficient implementation of anonymous functions.
 Supports functional programming: Works well with Java’s built-in functional
interfaces.

4. Using Lambda Expressions with Functional Interfaces


Since a lambda expression is essentially a function without a name, it can only be assigned to
a functional interface (an interface with exactly one abstract method).

Example 1: Using a Lambda with a Functional Interface


@FunctionalInterface
interface MyFunctionalInterface {
void show(); // Single abstract method
}
public class LambdaExample {
public static void main(String[] args) {
MyFunctionalInterface obj = () -> [Link]("Lambda
Expression Example");
[Link](); // Output: Lambda Expression Example
}
}

Explanation:

 MyFunctionalInterface has only one abstract method show().


 A lambda expression implements show() without needing a class.

5. Different Forms of Lambda Expressions


(a) Lambda with No Parameters
@FunctionalInterface
interface Greetings {
void sayHello();
}

public class LambdaNoParameter {


public static void main(String[] args) {
Greetings g = () -> [Link]("Hello, Lambda!");
[Link]();
}
}

Explanation:

 No parameters are used, so empty parentheses () are needed.

(b) Lambda with One Parameter


@FunctionalInterface
interface Message {
void printMessage(String msg);
}

public class LambdaOneParameter {


public static void main(String[] args) {
Message m = (msg) -> [Link]("Message: " + msg);
[Link]("Welcome to Java 8!");
}
}

Explanation:
 Since there is only one parameter, parentheses () around msg can be omitted.

(c) Lambda with Multiple Parameters


@FunctionalInterface
interface MathOperation {
int operate(int a, int b);
}

public class LambdaMultipleParameters {


public static void main(String[] args) {
MathOperation add = (a, b) -> a + b;
MathOperation multiply = (a, b) -> a * b;

[Link]("Sum: " + [Link](5, 3)); // Output:


Sum: 8
[Link]("Product: " + [Link](5, 3)); //
Output: Product: 15
}
}

Explanation:

 Two implementations are provided using lambdas:


o (a, b) -> a + b for addition.
o (a, b) -> a * b for multiplication.

(d) Lambda with a Return Statement


@FunctionalInterface
interface Square {
int calculate(int x);
}

public class LambdaReturn {


public static void main(String[] args) {
Square sq = (x) -> { return x * x; };
[Link]("Square of 4: " + [Link](4)); // Output:
16
}
}

Explanation:

 A lambda with a return statement needs curly braces {}.


 If there is only one statement, the {} and return keyword can be omitted:
 Square sq = x -> x * x;
6. Using Lambda Expressions with Java’s Built-in
Functional Interfaces
Java provides several built-in functional interfaces in [Link] that work well
with lambda expressions.

Example 1: Using Predicate<T> (Lambda for a Condition)


import [Link];

public class LambdaPredicate {


public static void main(String[] args) {
Predicate<Integer> isEven = n -> n % 2 == 0;

[Link]([Link](10)); // true
[Link]([Link](7)); // false
}
}

Explanation:

 Predicate<T> has a method test(T t) that returns true or false based on a


condition.

Example 2: Using Function<T, R> (Lambda for a Function)


import [Link];

public class LambdaFunction {


public static void main(String[] args) {
Function<String, Integer> lengthFinder = str -> [Link]();

[Link]([Link]("Lambda")); // Output: 6
}
}

Explanation:

 Function<T, R> takes one input and produces an output.

Example 3: Using Consumer<T> (Lambda for Performing an Action)


import [Link];

public class LambdaConsumer {


public static void main(String[] args) {
Consumer<String> print = str -> [Link]("Message: " +
str);
[Link]("Hello, Java!");
}
}

Explanation:

 Consumer<T> takes one input and performs an action without returning anything.

7. Using Lambda Expressions with Collections


Lambda expressions work well with Java Collections, especially for sorting and filtering.

Example 1: Sorting a List Using Lambda


import [Link].*;

public class LambdaSort {


public static void main(String[] args) {
List<String> names = [Link]("John", "Alice", "Bob");

[Link]((a, b) -> [Link](b)); // Sort alphabetically


[Link](names); // Output: [Alice, Bob, John]
}
}

Explanation:

 sort() takes a Comparator, which is implemented using a lambda.

Example 2: Filtering a List Using Lambda


import [Link].*;
import [Link];

public class LambdaFilter {


public static void main(String[] args) {
List<Integer> numbers = [Link](1, 2, 3, 4, 5, 6);

List<Integer> evenNumbers = [Link]()


.filter(n -> n % 2 == 0)
.collect([Link]());

[Link](evenNumbers); // Output: [2, 4, 6]


}
}

Explanation:

 filter() takes a Predicate lambda and returns only matching elements.


8. Method References with Lambda Expressions
Lambda expressions can be replaced with method references if an existing method matches
the required method signature.

Example: Method Reference Instead of Lambda


import [Link];

public class LambdaMethodReference {


public static void printMessage(String msg) {
[Link](msg);
}

public static void main(String[] args) {


Consumer<String> printer = LambdaMethodReference::printMessage;
[Link]("Using Method Reference!");
}
}

Explanation:

 Instead of msg -> printMessage(msg), we use


LambdaMethodReference::printMessage.

9. Summary
✅ Lambda expressions simplify functional interface implementation.
✅ Used with built-in functional interfaces like Predicate, Function, Consumer, and
Supplier.
✅ Makes code more readable and enables functional programming.
✅ Works well with collections and streams for filtering and sorting.
✅ Can be replaced with method references when applicable.

This should give you a complete understanding of Lambda Expressions in Java! Let me
know if you need more examples. 😊

Errors in Java
1. Introduction to Errors in Java
In Java, an error is a severe issue that occurs during the execution of a program, typically
beyond the programmer’s control. Errors can cause abnormal termination of a program and
are generally not recoverable. They belong to the [Link] class, which extends
[Link].

Errors differ from exceptions because they usually indicate problems that should not be
handled in the application code, such as memory issues or system crashes.

2. Types of Errors in Java


Errors in Java are broadly categorized into the following types:

1. Compile-time Errors (Syntax errors)


2. Runtime Errors (Errors during execution)
3. Logical Errors (Incorrect program logic)
4. Errors from [Link] Class (Severe system errors)

3. Compile-time Errors (Syntax Errors)


Compile-time errors occur before the program runs, during compilation. These errors prevent
the Java compiler from generating the bytecode (.class file).

Causes of Compile-time Errors

1. Syntax mistakes: Missing semicolons, mismatched braces, incorrect method


declarations.
2. Incorrect type usage: Assigning an integer to a string variable.
3. Undeclared variables: Using variables that have not been declared.
4. Misspelled keywords or class names.

Example of Compile-time Error


public class CompileTimeError {
public static void main(String[] args) {
int num = 10
[Link](num);
}
}

Error:

[Link]: error: ';' expected


int num = 10
^

Explanation:

 Missing semicolon (;) after int num = 10.


 The program won’t compile until the syntax is corrected.

4. Runtime Errors (Execution Errors)


Runtime errors occur during program execution and cause the program to crash if not
handled. These errors are caused by unexpected input, illegal operations, or incorrect
program logic.

Common Causes of Runtime Errors

1. Divide by zero (ArithmeticException)


2. Accessing invalid array index (ArrayIndexOutOfBoundsException)
3. Null reference usage (NullPointerException)
4. Invalid type casting (ClassCastException)
5. Insufficient memory (OutOfMemoryError)

Example of Runtime Error


public class RuntimeError {
public static void main(String[] args) {
int result = 10 / 0; // Divide by zero
[Link](result);
}
}

Error:

Exception in thread "main" [Link]: / by zero

Explanation:

 Dividing by zero is mathematically undefined, causing an ArithmeticException.


 To avoid this, check if the divisor is zero before performing division.

5. Logical Errors (Flaws in Logic)


Logical errors occur when a program runs without crashing but produces incorrect results.
These errors are difficult to detect because they do not generate error messages.

Example of Logical Error


public class LogicalError {
public static void main(String[] args) {
int num1 = 10, num2 = 5;
int sum = num1 - num2; // Incorrect logic
[Link]("Sum: " + sum);
}
}

Output:

Sum: 5

Explanation:

 The program should add (+) instead of subtracting (-).


 Logical errors require careful debugging and testing to identify.

6. Errors from the [Link] Class


Errors in the Error hierarchy are severe problems that occur beyond the control of the
application. They indicate failures at the JVM or system level.

Common Errors in Java

Error Type Description


StackOverflowError
Occurs when a method calls itself recursively without an
exit condition.
OutOfMemoryError Happens when the JVM runs out of memory.
NoClassDefFoundError Occurs when a required class is missing at runtime.
UnsupportedClassVersionError
Happens when a compiled .class file is run on an older
Java version.
AssertionError Raised when an assert statement fails.

6.1 StackOverflowError (Infinite Recursion)

A StackOverflowError occurs when a method calls itself indefinitely, causing the call stack
to exceed its limit.

Example

public class StackOverflowExample {


public static void recursiveMethod() {
recursiveMethod(); // Infinite recursion
}

public static void main(String[] args) {


recursiveMethod();
}
}

Error:

Exception in thread "main" [Link]


Fix:

 Add a base case in recursive methods to stop infinite recursion.

6.2 OutOfMemoryError (Insufficient Memory)

This error occurs when the JVM runs out of heap space due to excessive object allocation.

Example

import [Link];

public class OutOfMemoryExample {


public static void main(String[] args) {
ArrayList<int[]> list = new ArrayList<>();
while (true) {
[Link](new int[1000000]); // Allocating large arrays
indefinitely
}
}
}

Error:

Exception in thread "main" [Link]: Java heap space

Fix:

 Optimize memory usage by freeing unnecessary objects.


 Increase heap space using -Xmx JVM option (e.g., java -Xmx512m MyProgram).

7. Handling Errors with try-catch Blocks


Although errors should not be handled in most cases, runtime errors (exceptions) can be
handled using try-catch blocks.

Example: Handling Division by Zero Error


public class ErrorHandlingExample {
public static void main(String[] args) {
try {
int result = 10 / 0;
[Link](result);
} catch (ArithmeticException e) {
[Link]("Error: Division by zero is not allowed.");
}
}
}
Output:

Error: Division by zero is not allowed.

Explanation:

 The try block contains code that may throw an exception.


 The catch block handles the exception gracefully.

8. Difference Between Errors and Exceptions


Feature Errors Exceptions
Type Represent serious problems Represent recoverable problems
Recoverability Cannot be recovered from Can be handled using try-catch
StackOverflowError, ArithmeticException,
Examples OutOfMemoryError NullPointerException
Cause JVM-level issues Program-level issues

9. Summary
✅ Compile-time errors occur due to syntax mistakes.
✅ Runtime errors occur during execution (e.g., division by zero).
✅ Logical errors produce incorrect results without crashing.
✅ Errors from [Link] include StackOverflowError, OutOfMemoryError, and
NoClassDefFoundError.
✅ Errors should not be handled, but runtime exceptions can be caught using try-catch.

This should give you a detailed understanding of Errors in Java. Let me know if you need
further explanations! 🚀

Difference Between Errors and Exceptions


in Java
Java provides mechanisms to handle unexpected conditions that may occur during the
execution of a program. These conditions are categorized into Errors and Exceptions. Both
extend the Throwable class, but they have significant differences in their causes, handling,
and impact on a program.

1. Introduction
In Java, both errors and exceptions disrupt the normal flow of execution, but they serve
different purposes:

 Errors indicate serious problems that cannot be handled by the program.


 Exceptions indicate conditions that a program should handle to prevent failure.

Both errors and exceptions are represented in the class hierarchy as:

Throwable
├── Error ([Link])
├── Exception ([Link])
├── RuntimeException (Unchecked)
├── Other Exceptions (Checked)

2. Key Differences Between Errors and Exceptions


Feature Errors Exceptions
Serious issues that occur due to Problems that occur due to incorrect
Definition system-level failures or resource code or external conditions (e.g., user
exhaustion. input).
Generally not recoverable and Can be handled using try-catch or
Recoverability should not be handled in the other exception-handling
program. mechanisms.
Errors are not caught using try- Exceptions should be caught using
Handling
catch. try-catch or declared using throws.
Caused by system failures, such as Caused by programming mistakes
Causes memory exhaustion, JVM crashes, (e.g., null references, incorrect array
or stack overflow. indexing).
NullPointerException,
StackOverflowError,
ArithmeticException,
Examples OutOfMemoryError,
NoClassDefFoundError IOException,
FileNotFoundException
Inherits from [Link], Inherits from [Link],
Hierarchy
which extends Throwable. which extends Throwable.
Checked vs Always unchecked (i.e., not
Can be checked or unchecked.
Unchecked required to be handled).
Impact on Usually causes program Can be gracefully handled without
Program termination. terminating the program.

3. Errors in Java
Errors occur due to system-level failures and are usually beyond the control of the
programmer. These errors are part of [Link].

Common Errors
Error Type Description
StackOverflowError
Occurs due to infinite recursion, causing the call stack to
exceed its limit.
OutOfMemoryError Happens when the JVM runs out of memory.
NoClassDefFoundError
Occurs when the JVM cannot find a required class at
runtime.
UnsupportedClassVersionError
Happens when a .class file is compiled with a newer
JDK version than the JVM running it.

Example of an Error: StackOverflowError


public class StackOverflowExample {
public static void recursiveMethod() {
recursiveMethod(); // Infinite recursion
}

public static void main(String[] args) {


recursiveMethod();
}
}

Output:

Exception in thread "main" [Link]

Explanation:

 The method calls itself infinitely, exhausting stack memory.


 The JVM throws StackOverflowError, and the program terminates.

4. Exceptions in Java
Exceptions occur due to programming mistakes or unexpected external conditions (like file
not found, invalid input, etc.). They are recoverable and should be handled properly.

Types of Exceptions

Exceptions in Java are classified into Checked and Unchecked exceptions.

4.1 Checked Exceptions

 Checked at compile-time.
 The compiler forces the programmer to handle them using try-catch or throws.
 Example: IOException, SQLException, FileNotFoundException.

Example of a Checked Exception: IOException

import [Link].*;
public class CheckedExceptionExample {
public static void main(String[] args) {
try {
FileReader file = new FileReader("non_existent_file.txt");
} catch (IOException e) {
[Link]("File not found: " + [Link]());
}
}
}

Output:

File not found: non_existent_file.txt (No such file or directory)

Explanation:

 The file "non_existent_file.txt" does not exist, causing


FileNotFoundException (a subclass of IOException).
 This exception must be caught using try-catch, or the method must declare throws
IOException.

4.2 Unchecked Exceptions (Runtime Exceptions)

 Not checked at compile-time.


 Occur due to logical errors in the code.
 Example: NullPointerException, ArithmeticException,
ArrayIndexOutOfBoundsException.

Example of an Unchecked Exception: NullPointerException

public class UncheckedExceptionExample {


public static void main(String[] args) {
String str = null;
[Link]([Link]()); // NullPointerException
}
}

Output:

Exception in thread "main" [Link]

Explanation:

 The str variable is null, and calling .length() on it throws a


NullPointerException.
 Unlike checked exceptions, the compiler does not force handling of unchecked
exceptions.
5. Exception Handling in Java
Since exceptions should be handled, Java provides mechanisms like:

 try-catch: Catch exceptions and handle them gracefully.


 throws: Declare exceptions in the method signature.
 finally: Execute code whether an exception occurs or not.
 throw: Manually throw an exception.

Example: Handling Division by Zero


public class ExceptionHandlingExample {
public static void main(String[] args) {
try {
int result = 10 / 0;
[Link](result);
} catch (ArithmeticException e) {
[Link]("Error: Division by zero is not allowed.");
}
}
}

Output:

Error: Division by zero is not allowed.

Explanation:

 The try block attempts a division by zero.


 The catch block catches ArithmeticException and prevents program
termination.

6. When to Use Errors vs Exceptions?


 Use Errors (Error class) when the issue is critical and should not be handled (e.g.,
memory leaks, JVM crashes).
 Use Exceptions (Exception class) when the issue is recoverable (e.g., invalid user
input, missing files).

7. Summary
✅ Errors are system-level failures that cannot be handled (e.g., StackOverflowError).
✅ Exceptions are application-level issues that should be handled using try-catch.
✅ Checked exceptions must be handled at compile-time (e.g., IOException).
✅ Unchecked exceptions occur at runtime and do not require explicit handling (e.g.,
NullPointerException).
✅ Errors cause program termination, while exceptions can be recovered from.

This should give you a clear and detailed understanding of the differences between Errors
and Exceptions in Java. Let me know if you need more explanations! 🚀

Types of Exceptions in Java


Java provides a robust exception-handling mechanism that allows developers to detect and
manage runtime errors effectively. Exceptions are unexpected events that occur during
program execution, disrupting the normal flow of instructions.

Java exceptions are classified into two main types:

1. Checked Exceptions
2. Unchecked Exceptions (Runtime Exceptions)

Additionally, Java provides a separate category called User-Defined (Custom) Exceptions,


which programmers can create for specific application needs.

1. Hierarchy of Exceptions in Java


All exceptions in Java inherit from the [Link] class, which has two main
subclasses:

 Exception ([Link]) → Used for recoverable conditions.


 Error ([Link]) → Used for system-level failures that cannot be handled.

Throwable
├── Error (System-related issues, not recoverable)
├── Exception (Recoverable issues)
├── Checked Exceptions (Must be handled)
├── Unchecked Exceptions (Runtime exceptions)

2. Checked Exceptions (Compile-Time Exceptions)


Checked exceptions are exceptions that must be handled at compile-time using try-catch
or by declaring them with throws. If not handled, the program will not compile.

Common Checked Exceptions

Exception Description
IOException Occurs when an input-output operation fails, e.g., file not found.
Exception Description
SQLException Occurs when there is an issue with database operations.
FileNotFoundException Thrown when attempting to access a non-existent file.
InterruptedException Thrown when a thread is interrupted while sleeping or waiting.
ClassNotFoundException Occurs when a specified class is not found at runtime.

Example of Checked Exception: IOException


import [Link].*;

public class CheckedExceptionExample {


public static void main(String[] args) {
try {
FileReader file = new FileReader("non_existent_file.txt"); //
File does not exist
} catch (IOException e) {
[Link]("File not found: " + [Link]());
}
}
}

Output:

File not found: non_existent_file.txt (No such file or directory)

Explanation:

 The file "non_existent_file.txt" does not exist.


 FileReader throws FileNotFoundException, which must be handled.

3. Unchecked Exceptions (Runtime Exceptions)


Unchecked exceptions are exceptions that occur at runtime and do not require explicit
handling. The compiler does not check for these exceptions, and they usually arise from
programming mistakes.

Common Unchecked Exceptions

Exception Description
NullPointerException Occurs when trying to access an object that is null.
ArithmeticException
Occurs during arithmetic operations, such as division
by zero.
ArrayIndexOutOfBoundsException Thrown when accessing an array with an invalid index.

ClassCastException
Occurs when trying to cast an object to an
incompatible class.
NumberFormatException
Thrown when attempting to convert a string into a
numeric format that is invalid.
Example of Unchecked Exception: NullPointerException
public class UncheckedExceptionExample {
public static void main(String[] args) {
String str = null;
[Link]([Link]()); // NullPointerException
}
}

Output:

Exception in thread "main" [Link]

Explanation:

 Since str is null, calling .length() on it throws NullPointerException.


 The compiler does not force handling of this exception.

4. Differences Between Checked and Unchecked


Exceptions
Feature Checked Exceptions Unchecked Exceptions
Compile-
time Checked at compile-time Not checked at compile-time
Checking
Handling Must be handled using try-
Handling is optional
Required? catch or throws
External factors (e.g., missing Programming errors (e.g., null references,
Cause
files, database errors) array index issues)
NullPointerException,
IOException, SQLException,
Examples FileNotFoundException ArithmeticException,
ArrayIndexOutOfBoundsException

5. User-Defined (Custom) Exceptions


Java allows developers to create custom exceptions by extending the Exception or
RuntimeException class.

Steps to Create a Custom Exception

1. Create a class that extends Exception (for checked exceptions) or


RuntimeException (for unchecked exceptions).
2. Define constructors and pass messages.
3. Throw the custom exception in the program.
Example: Custom Exception for Invalid Age
class InvalidAgeException extends Exception {
public InvalidAgeException(String message) {
super(message);
}
}

public class CustomExceptionExample {


static void validateAge(int age) throws InvalidAgeException {
if (age < 18) {
throw new InvalidAgeException("Age must be 18 or above.");
} else {
[Link]("Valid age.");
}
}

public static void main(String[] args) {


try {
validateAge(16);
} catch (InvalidAgeException e) {
[Link]("Caught Exception: " + [Link]());
}
}
}

Output:

Caught Exception: Age must be 18 or above.

Explanation:

 InvalidAgeException is a custom exception.


 If the age is below 18, the exception is thrown and caught in the catch block.

6. Exception Handling Techniques in Java


Java provides multiple ways to handle exceptions:

6.1 Using try-catch


try {
int result = 10 / 0; // Division by zero
} catch (ArithmeticException e) {
[Link]("Cannot divide by zero.");
}

6.2 Using throws


void riskyMethod() throws IOException {
throw new IOException("Error occurred");
}
6.3 Using finally
try {
[Link]("Inside try block");
} finally {
[Link]("This will always execute.");
}

6.4 Using throw


throw new IllegalArgumentException("Invalid input");

7. Summary
✅ Checked Exceptions must be handled at compile-time (e.g., IOException).
✅ Unchecked Exceptions occur at runtime and are not mandatory to handle (e.g.,
NullPointerException).
✅ User-Defined Exceptions can be created for custom validation logic.
✅ Exception handling techniques include try-catch, throws, finally, and throw.

This is a detailed explanation of the types of exceptions in Java. Let me know if you need
further clarifications! 🚀

Exception Handling in Java


1. Introduction to Exception Handling
Exception handling in Java is a mechanism that allows programs to handle runtime errors
gracefully. Instead of abruptly terminating, Java provides ways to detect, handle, and
recover from errors using exception handling techniques.

What is an Exception?

An exception is an unexpected event that occurs during program execution, disrupting the
normal flow of instructions.

Why Use Exception Handling?

 Prevents abrupt termination of the program.


 Provides a structured approach to handle errors.
 Improves code readability and maintainability.
 Allows programs to recover gracefully from errors.
2. Exception Hierarchy in Java
All exceptions in Java are derived from the Throwable class. It has two main subclasses:

1. Exception ([Link]) → Represents errors that can be handled (e.g.,


IOException, SQLException).
2. Error ([Link]) → Represents serious system errors that cannot be
handled (e.g., OutOfMemoryError).

Throwable
├── Error (System-level failures, not recoverable)
├── Exception (Recoverable issues)
├── Checked Exceptions (Must be handled)
├── Unchecked Exceptions (Runtime exceptions)

3. Exception Handling Mechanisms in Java


Java provides five key mechanisms for handling exceptions:

1. try-catch Block

 Used to handle exceptions where the risky code is placed inside the try block, and
the handling logic is written inside the catch block.

Syntax:

try {
// Code that may throw an exception
} catch (ExceptionType e) {
// Handling code
}

Example: Handling Division by Zero (ArithmeticException)

public class TryCatchExample {


public static void main(String[] args) {
try {
int result = 10 / 0; // Causes ArithmeticException
} catch (ArithmeticException e) {
[Link]("Error: Cannot divide by zero.");
}
}
}

Output:

Error: Cannot divide by zero.

2. try-catch-finally Block
 The finally block always executes, regardless of whether an exception occurs or
not.
 Typically used to release resources (e.g., closing a file or database connection).

Example: Using finally

public class FinallyExample {


public static void main(String[] args) {
try {
int[] arr = {1, 2, 3};
[Link](arr[5]); // ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
[Link]("Invalid array index.");
} finally {
[Link]("This block always executes.");
}
}
}

Output:

Invalid array index.


This block always executes.

3. throws Keyword

 Used to declare exceptions in a method signature, indicating that the method might
throw an exception.
 The calling method must handle the exception.

Syntax:

returnType methodName() throws ExceptionType {


// Method logic
}

Example: Declaring an Exception Using throws

import [Link].*;

public class ThrowsExample {


static void readFile() throws IOException {
FileReader file = new FileReader("[Link]"); // File might not
exist
}

public static void main(String[] args) {


try {
readFile();
} catch (IOException e) {
[Link]("File not found.");
}
}
}
Output:

File not found.

Explanation:

 readFile() declares that it might throw an IOException.


 The main() method handles it using try-catch.

4. throw Keyword

 Used to explicitly throw an exception in Java.

Syntax:

throw new ExceptionType("Error message");

Example: Throwing an Exception

public class ThrowExample {


static void checkAge(int age) {
if (age < 18) {
throw new IllegalArgumentException("Age must be 18 or above.");
}
}

public static void main(String[] args) {


checkAge(16); // Throws exception
}
}

Output:

Exception in thread "main" [Link]: Age must be


18 or above.

Explanation:

 throw is used to manually throw an IllegalArgumentException.

5. Custom (User-Defined) Exceptions

 Java allows creating custom exceptions by extending the Exception or


RuntimeException class.

Example: Creating a Custom Exception

class InvalidAgeException extends Exception {


public InvalidAgeException(String message) {
super(message);
}
}

public class CustomExceptionExample {


static void validate(int age) throws InvalidAgeException {
if (age < 18) {
throw new InvalidAgeException("Age is below 18.");
}
}

public static void main(String[] args) {


try {
validate(16);
} catch (InvalidAgeException e) {
[Link]("Caught Exception: " + [Link]());
}
}
}

Output:

Caught Exception: Age is below 18.

Explanation:

 InvalidAgeException is a custom exception extending Exception.

4. Exception Propagation
 If an exception is not handled in the current method, it propagates to the caller
method.
 Exception propagation follows a bottom-up approach in the call stack.

Example of Exception Propagation

public class ExceptionPropagationExample {


static void method1() {
int result = 10 / 0; // ArithmeticException
}

static void method2() {


method1(); // Exception propagates to method2()
}

public static void main(String[] args) {


try {
method2(); // Exception propagates here
} catch (ArithmeticException e) {
[Link]("Caught Exception: " + e);
}
}
}
Output:

Caught Exception: [Link]: / by zero

Explanation:

 method1() throws an exception.


 It propagates to method2(), then to main(), where it is handled.

5. Difference Between throw and throws


Feature throw throws
Declares exceptions that a method
Purpose Used to explicitly throw an exception.
can throw.
Usage Inside a method body. In method signature.
void method() throws
Syntax throw new ExceptionType("Message");
ExceptionType { }
throw new NullPointerException("Null void readFile() throws
Example value!"); IOException { }

6. Best Practices for Exception Handling


✅ Catch Specific Exceptions (Avoid using catch(Exception e)).
✅ Use finally to Release Resources (E.g., close files, database connections).
✅ Avoid Empty catch Blocks (Always log or handle exceptions).
✅ Use Meaningful Exception Messages (Helps in debugging).
✅ Don't Ignore Checked Exceptions (Use throws or try-catch).

7. Summary
✔ Exception handling prevents program crashes.
✔ Java provides try-catch, finally, throws, and throw for handling exceptions.
✔ Checked exceptions must be handled, while unchecked exceptions occur at runtime.
✔ Exception propagation moves an exception up the call stack.
✔ Custom exceptions allow defining application-specific error handling.

This is a detailed explanation of Exception Handling in Java. Let me know if you need
further clarifications! 🚀

Java’s Built-in Exceptions


1. Introduction to Built-in Exceptions
Java provides a rich set of built-in exceptions to handle common runtime errors. These
exceptions belong to the Java Exception Hierarchy, which is part of the [Link]
package.

Why Use Built-in Exceptions?

 Saves time since these exceptions are predefined.


 Helps in debugging errors effectively.
 Provides meaningful error messages.

2. Java Exception Hierarchy


Throwable
├── Exception (Recoverable, application-level issues)
│ ├── IOException
│ ├── SQLException
│ ├── RuntimeException (Unchecked exceptions)
│ ├── NullPointerException
│ ├── ArithmeticException
│ ├── ArrayIndexOutOfBoundsException
│ ├── IllegalArgumentException
│ ├── NumberFormatException
│ ├── ClassCastException
│ ├── IllegalStateException
├── Error (Critical, system-level failures)
├── StackOverflowError
├── OutOfMemoryError
├── VirtualMachineError

3. Types of Built-in Exceptions in Java


Java’s built-in exceptions are broadly categorized into Checked Exceptions and Unchecked
Exceptions.

A. Checked Exceptions (Compile-time Exceptions)

 Checked at compile time.


 Must be either handled using try-catch or declared using throws.
 Typically related to I/O operations, database access, networking, etc.

Examples of Checked Exceptions


Exception Description
IOException Raised when an input-output operation fails.
SQLException Occurs during database operations.
FileNotFoundException Raised when the specified file is not found.
InterruptedException Thrown when a thread is interrupted.
ClassNotFoundException Raised when a class is not found.

Example: Handling IOException

import [Link].*;

public class CheckedExceptionExample {


public static void main(String[] args) {
try {
FileReader file = new FileReader("[Link]");
} catch (FileNotFoundException e) {
[Link]("Error: File not found!");
}
}
}

Output:

Error: File not found!

B. Unchecked Exceptions (Runtime Exceptions)

 Checked at runtime (not at compile time).


 Do not require explicit handling.
 Occur due to logic errors or incorrect code.

Examples of Unchecked Exceptions

Exception Description
NullPointerException Accessing a null reference.
ArithmeticException Division by zero error.
ArrayIndexOutOfBoundsException Accessing an invalid array index.
IllegalArgumentException Passed an invalid argument.
ClassCastException Invalid typecasting.
NumberFormatException Converting invalid string to number.

Example: Handling ArithmeticException

public class UncheckedExceptionExample {


public static void main(String[] args) {
try {
int result = 10 / 0; // Division by zero
} catch (ArithmeticException e) {
[Link]("Cannot divide by zero!");
}
}
}

Output:

Cannot divide by zero!

4. Common Java Built-in Exceptions with Examples


1. NullPointerException

Occurs when trying to access a method or variable of a null object.

public class NullPointerExample {


public static void main(String[] args) {
String text = null;
try {
[Link]([Link]()); // NullPointerException
} catch (NullPointerException e) {
[Link]("Null reference encountered!");
}
}
}

Output:

Null reference encountered!

2. ArrayIndexOutOfBoundsException

Occurs when accessing an invalid index of an array.

public class ArrayIndexExample {


public static void main(String[] args) {
int[] arr = {1, 2, 3};
try {
[Link](arr[5]); // Out of bounds
} catch (ArrayIndexOutOfBoundsException e) {
[Link]("Array index out of bounds!");
}
}
}

Output:

Array index out of bounds!

3. NumberFormatException

Occurs when converting an invalid string into a number.


public class NumberFormatExample {
public static void main(String[] args) {
try {
int num = [Link]("abc"); // Invalid number
} catch (NumberFormatException e) {
[Link]("Invalid number format!");
}
}
}

Output:

Invalid number format!

4. ClassCastException

Occurs when trying to cast an object to an incompatible type.

public class ClassCastExample {


public static void main(String[] args) {
Object obj = new String("Hello");
try {
Integer num = (Integer) obj; // Invalid cast
} catch (ClassCastException e) {
[Link]("Class cast exception occurred!");
}
}
}

Output:

Class cast exception occurred!

5. IllegalArgumentException

Occurs when an invalid argument is passed to a method.

public class IllegalArgumentExample {


static void checkAge(int age) {
if (age < 18) {
throw new IllegalArgumentException("Age must be 18 or above.");
}
}

public static void main(String[] args) {


try {
checkAge(16);
} catch (IllegalArgumentException e) {
[Link]([Link]());
}
}
}

Output:
Age must be 18 or above.

6. StackOverflowError

Occurs when a method calls itself infinitely (infinite recursion).

public class StackOverflowExample {


public static void recursiveMethod() {
recursiveMethod(); // Infinite recursion
}

public static void main(String[] args) {


recursiveMethod();
}
}

Output:

Exception in thread "main" [Link]

7. OutOfMemoryError

Occurs when JVM runs out of memory.

import [Link].*;

public class OutOfMemoryExample {


public static void main(String[] args) {
List<int[]> list = new ArrayList<>();
while (true) {
[Link](new int[1000000]); // Consumes memory
}
}
}

Output:

Exception in thread "main" [Link]: Java heap space

5. Summary Table of Built-in Exceptions


Exception Name Type Cause
IOException Checked Issues in file handling.
SQLException Checked Errors in database operations.
FileNotFoundException Checked File does not exist.
NullPointerException Unchecked Accessing null reference.
ArithmeticException Unchecked Division by zero.
ArrayIndexOutOfBoundsException Unchecked Invalid array index.
NumberFormatException Unchecked Invalid conversion of string to number.
Exception Name Type Cause
ClassCastException Unchecked Incompatible type casting.
IllegalArgumentException Unchecked Invalid arguments passed.
StackOverflowError Error Infinite recursion.
OutOfMemoryError Error JVM runs out of memory.

6. Conclusion
✔ Java provides built-in exceptions for handling common errors.
✔ Checked exceptions must be handled, while unchecked exceptions occur at runtime.
✔ Errors like StackOverflowError and OutOfMemoryError are critical and cannot be
recovered.

This was a detailed explanation of Java's Built-in Exceptions. Let me know if you need
more clarity! 🚀

Custom Exceptions in Java


1. Introduction to Custom Exceptions
Java allows developers to define their own exceptions, known as Custom Exceptions or
User-Defined Exceptions. These are useful when Java’s built-in exceptions do not
adequately describe a particular error scenario in an application.

2. Why Use Custom Exceptions?


✅ Makes the code more readable and meaningful by giving specific names to errors.
✅ Helps in handling application-specific errors effectively.
✅ Improves maintainability and debugging.

3. Defining Custom Exceptions


Steps to Create a Custom Exception

1. Extend the Exception class (for a checked exception) or the RuntimeException


class (for an unchecked exception).
2. Provide a constructor to initialize the exception message.
3. Override methods (optional) like toString() or getMessage() for additional
functionality.
4. Types of Custom Exceptions
A. Checked Custom Exceptions (Extends Exception)

 Must be either handled using try-catch or declared using throws.


 Suitable for situations where recovery is possible (e.g., invalid user input).

Example: Creating a Checked Custom Exception

// Custom Checked Exception


class InvalidAgeException extends Exception {
public InvalidAgeException(String message) {
super(message); // Call Exception class constructor
}
}

public class CustomCheckedExample {


// Method that throws the custom exception
static void validateAge(int age) throws InvalidAgeException {
if (age < 18) {
throw new InvalidAgeException("Age must be at least 18.");
} else {
[Link]("Age is valid.");
}
}

public static void main(String[] args) {


try {
validateAge(16); // This will throw an exception
} catch (InvalidAgeException e) {
[Link]("Caught Exception: " + [Link]());
}
}
}

Output:

Caught Exception: Age must be at least 18.

B. Unchecked Custom Exceptions (Extends RuntimeException)

 Does not require explicit handling.


 Suitable for programming logic errors (e.g., division by zero, invalid arguments).

Example: Creating an Unchecked Custom Exception

// Custom Unchecked Exception


class NegativeNumberException extends RuntimeException {
public NegativeNumberException(String message) {
super(message);
}
}
public class CustomUncheckedExample {
static void checkNumber(int num) {
if (num < 0) {
throw new NegativeNumberException("Number cannot be
negative.");
} else {
[Link]("Valid number: " + num);
}
}

public static void main(String[] args) {


checkNumber(-5); // This will throw an exception
}
}

Output:

Exception in thread "main" NegativeNumberException: Number cannot be


negative.

5. Best Practices for Custom Exceptions


✔ Use meaningful names for custom exceptions (e.g., InvalidAgeException).
✔ Extend Exception for checked exceptions and RuntimeException for unchecked
exceptions.
✔ Include descriptive messages in the constructor to provide meaningful error messages.
✔ Avoid unnecessary custom exceptions—use built-in exceptions if they suffice.
✔ Provide constructors that allow message customization.

6. Summary Table
Exception Type Inherits From Needs to be Handled? Usage
Checked Exception
✅ Yes (must use try- Use when the application can
Exception catch or throws) recover from the error.
Unchecked RuntimeException
❌ No (optional Use when the error is due to
Exception handling) programming mistakes.

7. Conclusion
✔ Custom exceptions provide more meaningful error messages.
✔ Checked exceptions are used when errors can be anticipated and handled.
✔ Unchecked exceptions are used for programming logic errors.
✔ They enhance debugging and improve code clarity.

This was a detailed explanation of Custom Exceptions in Java. Let me know if you need
more clarity! 🚀
Exception Logging in Java
1. Introduction to Exception Logging
Exception logging is the process of recording information about exceptions that occur during
program execution. It helps in debugging, troubleshooting, and monitoring application
behavior.

2. Why Use Exception Logging?


✅ Helps in Debugging: Provides a detailed trace of where and why an error occurred.
✅ Enhances Maintainability: Makes it easier for developers to find and fix issues.
✅ Stores Error Details: Keeps logs for future reference, even after the application has
stopped.
✅ Supports Monitoring & Alerts: Can be used to detect recurring issues in production
environments.

3. Ways to Log Exceptions in Java


A. Using printStackTrace() (Basic Method)

 Prints the exception details and stack trace to the console.


 Not recommended for real-world applications because it does not persist logs.

Example:

public class PrintStackTraceExample {


public static void main(String[] args) {
try {
int result = 10 / 0; // ArithmeticException
} catch (ArithmeticException e) {
[Link](); // Logs exception details to console
}
}
}

Output:

[Link]: / by zero
at [Link]([Link])

B. Using [Link]() (Simple Logging)

 Logs the exception message to [Link] (standard error stream).


 Better than printStackTrace() but still lacks persistence.

Example:

public class SystemErrExample {


public static void main(String[] args) {
try {
String text = null;
[Link]([Link]()); // NullPointerException
} catch (NullPointerException e) {
[Link]("Error: " + [Link]());
}
}
}

Output:

Error: Cannot invoke "[Link]()" because "text" is null

C. Using Java Logging ([Link])

 Uses Java’s built-in logging framework ([Link]).


 Provides different log levels (INFO, WARNING, SEVERE, etc.).
 Allows writing logs to files.

Example:

import [Link].*;

public class JavaLoggingExample {


private static final Logger logger =
[Link]([Link]());

public static void main(String[] args) {


try {
int[] arr = {1, 2, 3};
[Link](arr[5]); // ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
[Link]([Link], "Exception Occurred", e);
}
}
}

Output in Console:

SEVERE: Exception Occurred


[Link]: Index 5 out of bounds for length
3
at [Link]([Link])

D. Using Apache Log4j (Recommended for Large Applications)


Apache Log4j is a powerful logging library with log levels, file storage, and formatting
options.

Steps to Use Log4j

1. Add Log4j dependency (if using Maven):


2. <dependencies>
3. <dependency>
4. <groupId>log4j</groupId>
5. <artifactId>log4j</artifactId>
6. <version>1.2.17</version>
7. </dependency>
8. </dependencies>
9. Create a [Link] file:
10. [Link]=DEBUG, file
11.
12. [Link]=[Link]
13. [Link]=[Link]
14. [Link]=[Link]
15. [Link]=%d [%t] %-5p %c - %m%n
16. Use Log4j in Java Code:
17. import [Link];
18.
19. public class Log4jExample {
20. private static final Logger logger =
[Link]([Link]);
21.
22. public static void main(String[] args) {
23. try {
24. int num = [Link]("abc"); //
NumberFormatException
25. } catch (NumberFormatException e) {
26. [Link]("Invalid number format", e);
27. }
28. }
29. }

Log Output ([Link] file):

2025-04-03 14:55:02 [main] ERROR Log4jExample - Invalid number format


[Link]: For input string: "abc"
at
[Link]/[Link](NumberFormatExcept
[Link])

E. Using SLF4J with Logback (Modern Approach)

SLF4J (Simple Logging Facade for Java) provides a unified interface for different logging
frameworks (Log4j, Logback).

Steps to Use SLF4J with Logback

1. Add Maven dependencies:


2. <dependency>
3. <groupId>[Link]</groupId>
4. <artifactId>logback-classic</artifactId>
5. <version>1.2.11</version>
6. </dependency>
7. <dependency>
8. <groupId>org.slf4j</groupId>
9. <artifactId>slf4j-api</artifactId>
10. <version>1.7.32</version>
11. </dependency>
12. Create a [Link] file:
13. <configuration>
14. <appender name="FILE" class="[Link]">
15. <file>[Link]</file>
16. <encoder>
17. <pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} -
%msg%n</pattern>
18. </encoder>
19. </appender>
20.
21. <root level="info">
22. <appender-ref ref="FILE" />
23. </root>
24. </configuration>
25. Use SLF4J in Java Code:
26. import [Link];
27. import [Link];
28.
29. public class SLF4JExample {
30. private static final Logger logger =
[Link]([Link]);
31.
32. public static void main(String[] args) {
33. try {
34. int num = 10 / 0; // ArithmeticException
35. } catch (ArithmeticException e) {
36. [Link]("Division by zero error", e);
37. }
38. }
39. }

Log Output ([Link] file):

2025-04-03 15:00:15 ERROR SLF4JExample - Division by zero error


[Link]: / by zero
at [Link]([Link])

6. Summary Table
Method Pros Cons
Only prints to console, no
printStackTrace() Easy to use
persistence
No stack trace, difficult to
[Link]() Simple
analyze later
[Link] Built-in, supports log levels Limited flexibility
Advanced logging, supports
Apache Log4j Requires additional setup
files
Method Pros Cons
Modern, flexible, widely
SLF4J with Logback Requires dependencies
used

7. Conclusion
✔ Exception logging is essential for debugging and monitoring applications.
✔ Built-in Java Logging ([Link]) is simple but limited.
✔ Log4j and SLF4J with Logback are the most efficient and professional solutions.
✔ Persisting logs in files helps in long-term tracking and analysis.

This was a detailed explanation of Exception Logging in Java! Let me know if you need
further clarification. 🚀
MODULE – 3

Threads in Java: Creating, Implementing, and Extending Threads

In Java, a thread is the smallest unit of execution within a process. Java provides built-in
support for multithreading, allowing programs to execute multiple tasks concurrently.

1. What is a Thread in Java?


A thread is an independent path of execution within a program. Java provides a built-in
Thread class and a Runnable interface to work with threads.

A Java program can have multiple threads, allowing tasks to execute in parallel. The Java
Virtual Machine (JVM) handles thread scheduling.

2. Ways to Create a Thread in Java


There are three main ways to create a thread in Java:

1. By extending the Thread class


2. By implementing the Runnable interface
3. By using the Callable and Future interfaces (used when a thread needs to return a
result)

3. Method 1: Creating a Thread by Extending the Thread


Class
Java provides a built-in Thread class, which can be extended to create a new thread.

Steps to Extend Thread Class:

1. Create a class that extends the Thread class.


2. Override the run() method (this method contains the code to be executed by the
thread).
3. Create an object of the class and call start() to begin execution.

Example:
class MyThread extends Thread {
public void run() {
[Link]("Thread is running...");
}

public static void main(String args[]) {


MyThread t1 = new MyThread();
[Link](); // Start the thread
}
}

Explanation:

 The run() method contains the logic that the thread will execute.
 The start() method is used to initiate the thread, which internally calls run().

Advantages of Extending Thread Class

✔ Simple and easy to implement.


✔ Direct access to Thread class methods.

Disadvantages

❌ Java does not support multiple inheritance, so extending Thread class prevents inheriting
from another class.

4. Method 2: Creating a Thread by Implementing the


Runnable Interface

Java provides a Runnable interface that can be implemented to define a thread.

Steps to Implement Runnable Interface:

1. Create a class that implements the Runnable interface.


2. Override the run() method.
3. Create a Thread object and pass the instance of the class to the Thread constructor.
4. Call start() to begin execution.

Example:
class MyRunnable implements Runnable {
public void run() {
[Link]("Thread is running using Runnable...");
}

public static void main(String args[]) {


MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
[Link](); // Start the thread
}
}

Explanation:

 The class implements Runnable and overrides run().


 A Runnable object is passed to a Thread object.
 start() begins execution of the thread.

Advantages of Implementing Runnable

✔ Allows multiple inheritance (the class can extend another class while implementing
Runnable).
✔ Better separation of thread code from the main class.

Disadvantages

❌ Requires additional steps to create a Thread object.

5. Method 3: Using Callable and Future (When Return Value


is Needed)
Unlike Runnable, the Callable interface allows a thread to return a result and throw
exceptions.

Steps to Implement Callable:

1. Create a class that implements Callable<T>, where T is the return type.


2. Override the call() method instead of run().
3. Use ExecutorService and Future to execute the thread and retrieve the result.

Example:
import [Link];
import [Link];
import [Link];
import [Link];

class MyCallable implements Callable<Integer> {


public Integer call() {
return 10 * 10;
}

public static void main(String args[]) {


ExecutorService executor = [Link]();
Future<Integer> future = [Link](new MyCallable());

try {
[Link]("Result from Callable: " + [Link]()); //
Get result
} catch (Exception e) {
[Link]();
}

[Link]();
}
}

Explanation:

 Callable<Integer> is used instead of Runnable.


 The call() method returns a result.
 ExecutorService manages thread execution.
 [Link]() retrieves the returned value.

Advantages of Callable

✔ Can return a result.


✔ Can throw exceptions.

Disadvantages

❌ Slightly more complex than Runnable.

6. Extending and Implementing Threads


Java allows the use of both inheritance (Thread class) and interface (Runnable).

Example: Using Both Thread and Runnable


class MyThread extends Thread implements Runnable {
public void run() {
[Link]("Thread running with both Thread and
Runnable...");
}

public static void main(String args[]) {


MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
[Link]();
}
}

When to Use What?

Scenario Approach
Need to override Thread methods Extend Thread
Need to inherit another class Implement Runnable
Need a return value Use Callable
7. Thread Lifecycle in Java
A thread in Java has five states:

1. New (Created) → Thread object is created but not started (new Thread()).
2. Runnable → Thread is ready to run but waiting for CPU time.
3. Running → Thread is currently executing.
4. Blocked/Waiting → Thread is paused due to some condition (e.g., waiting for a
resource).
5. Terminated (Dead) → Thread has finished execution.

Example: Observing Thread States


class MyThread extends Thread {
public void run() {
[Link]("Thread Running...");
}

public static void main(String args[]) {


MyThread t1 = new MyThread();
[Link]("Thread state: " + [Link]()); // New
[Link]();
[Link]("Thread state after start: " +
[Link]()); // Runnable
}
}

8. Conclusion
 Java provides multiple ways to create and manage threads.
 Extending Thread class is simple but limits inheritance.
 Implementing Runnable interface allows flexibility and multiple inheritance.
 Using Callable and Future is useful when a return value is needed.
 Java threads go through a lifecycle of states.
 Proper thread management is important to avoid race conditions and deadlocks.

Would you like me to include details on thread synchronization, thread pool, or inter-
thread communication? 🚀

Thread Priorities in Java


1. Introduction to Thread Priority
In Java, every thread is assigned a priority, which helps determine the order in which
threads are scheduled for execution by the CPU. Thread priority in Java is represented as an
integer value between 1 and 10, where:
 Thread.MIN_PRIORITY = 1 (Lowest priority)
 Thread.NORM_PRIORITY = 5 (Default priority)
 Thread.MAX_PRIORITY = 10 (Highest priority)

Higher-priority threads may get CPU time before lower-priority threads, but it is not
guaranteed, as thread scheduling depends on the JVM and the OS scheduler.

2. How to Set and Get Thread Priority in Java


The priority of a thread can be set using the setPriority(int priority) method and
retrieved using the getPriority() method.

Syntax:
void setPriority(int priority) // Sets thread priority
int getPriority() // Returns thread priority

Example: Setting and Getting Thread Priority


class MyThread extends Thread {
public void run() {
[Link]([Link]().getName() + " Priority: "
+ [Link]().getPriority());
}

public static void main(String[] args) {


MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();

[Link](Thread.MIN_PRIORITY); // Priority = 1
[Link](Thread.NORM_PRIORITY); // Priority = 5
[Link](Thread.MAX_PRIORITY); // Priority = 10

[Link]();
[Link]();
[Link]();
}
}

Output (May vary)


Thread-1 Priority: 5
Thread-2 Priority: 10
Thread-0 Priority: 1

Note: The execution order is not guaranteed, even though t3 has the highest priority.

3. Default Thread Priority in Java


 If the priority is not explicitly set, it defaults to 5 (NORM_PRIORITY).
 A thread inherits the priority of the parent thread that created it.

Example: Default Priority


class DefaultPriorityThread extends Thread {
public void run() {
[Link]([Link]().getName() + " Default
Priority: " + [Link]().getPriority());
}

public static void main(String[] args) {


DefaultPriorityThread t1 = new DefaultPriorityThread();
[Link](); // Priority will be inherited (default 5)
}
}

Output
Thread-0 Default Priority: 5

4. Does Thread Priority Guarantee Execution Order?


No!

 Thread priority is just a suggestion to the JVM.


 The actual scheduling depends on the operating system’s thread scheduler
(preemptive or time-sliced scheduling).
 Even a high-priority thread might not execute immediately.

5. Example: Impact of Thread Priority on Execution


Let’s create multiple threads and observe how priority affects execution:

class PriorityExample extends Thread {


public void run() {
for (int i = 0; i < 3; i++) {
[Link]([Link]().getName() + " running
with priority: " + [Link]().getPriority());
}
}

public static void main(String[] args) {


PriorityExample t1 = new PriorityExample();
PriorityExample t2 = new PriorityExample();
PriorityExample t3 = new PriorityExample();

[Link](Thread.MIN_PRIORITY); // 1
[Link](Thread.NORM_PRIORITY); // 5
[Link](Thread.MAX_PRIORITY); // 10
[Link]();
[Link]();
[Link]();
}
}

Possible Output
Thread-2 running with priority: 10
Thread-2 running with priority: 10
Thread-2 running with priority: 10
Thread-1 running with priority: 5
Thread-1 running with priority: 5
Thread-1 running with priority: 5
Thread-0 running with priority: 1
Thread-0 running with priority: 1
Thread-0 running with priority: 1

In this example, Thread-2 (priority 10) gets more CPU time, but execution order is still
unpredictable.

6. When to Use Thread Priorities?


Use thread priorities when: ✔ You want important tasks to have a better chance of
executing first.
✔ You are working with real-time applications, where some tasks must complete before
others.

However, avoid relying solely on thread priorities because: ❌ They do not guarantee
execution order.
❌ The behavior varies across different operating systems and JVM implementations.

7. Summary
 Java assigns priorities from 1 to 10 to threads.
 Default priority is 5 (NORM_PRIORITY).
 The setPriority() method sets the priority, and getPriority() retrieves it.
 Higher priority threads do not always execute first; scheduling depends on the
JVM and OS.
 Thread priorities should not be used as the only way to manage execution order.

Would you like me to cover thread scheduling algorithms or synchronization concepts


next? 🚀
Thread Synchronization and Suspending in
Java
1. Introduction to Synchronization in Java
When multiple threads access shared resources simultaneously, data inconsistency and race
conditions can occur. Synchronization in Java ensures that only one thread at a time can
access a shared resource, preventing conflicts.

Java provides three ways to achieve synchronization:

1. Synchronized Methods
2. Synchronized Blocks
3. Using Locks (Explicit Locking with ReentrantLock)

2. The synchronized Keyword


The synchronized keyword in Java restricts access to a critical section so that only one
thread can execute it at a time.

Example: Without Synchronization (Race Condition)


class Counter {
int count = 0;

void increment() { // No synchronization


count++;
}

public static void main(String[] args) {


Counter c = new Counter();

Thread t1 = new Thread(() -> {


for (int i = 0; i < 1000; i++) {
[Link]();
}
});

Thread t2 = new Thread(() -> {


for (int i = 0; i < 1000; i++) {
[Link]();
}
});

[Link]();
[Link]();

try {
[Link]();
[Link]();
} catch (InterruptedException e) {
[Link]();
}

[Link]("Final Count: " + [Link]);


}
}

Possible Output (Incorrect)


Final Count: 1875 (Expected: 2000)

The output is inconsistent due to race conditions.

3. Synchronizing a Method
To avoid race conditions, we use synchronized methods.

Example: Using a Synchronized Method


class Counter {
int count = 0;

synchronized void increment() { // Synchronized method


count++;
}

public static void main(String[] args) {


Counter c = new Counter();

Thread t1 = new Thread(() -> {


for (int i = 0; i < 1000; i++) {
[Link]();
}
});

Thread t2 = new Thread(() -> {


for (int i = 0; i < 1000; i++) {
[Link]();
}
});

[Link]();
[Link]();

try {
[Link]();
[Link]();
} catch (InterruptedException e) {
[Link]();
}

[Link]("Final Count: " + [Link]);


}
}
Correct Output
Final Count: 2000

The synchronized keyword ensures that only one thread modifies count at a time.

4. Synchronizing a Block (More Efficient)


Instead of synchronizing the entire method, we can synchronize only the critical section.

Example: Using a Synchronized Block


class Counter {
int count = 0;

void increment() {
synchronized (this) { // Synchronized block
count++;
}
}
}

 This improves efficiency by locking only the necessary part of the method.

5. Using Locks (ReentrantLock)


Java provides the ReentrantLock class (part of [Link]) for explicit
thread synchronization.

Example: Using ReentrantLock


import [Link];
import [Link];

class Counter {
int count = 0;
Lock lock = new ReentrantLock();

void increment() {
[Link](); // Acquire lock
try {
count++;
} finally {
[Link](); // Release lock
}
}
}
 Unlike synchronized, ReentrantLock provides more control and allows tryLock()
for non-blocking attempts.

6. Suspending a Thread
A thread can be temporarily suspended using the following methods:

1. sleep() - Makes the thread pause for a fixed time.


2. wait() - Waits until another thread notifies it.
3. suspend() and resume() (Deprecated) - Suspends and resumes a thread.

Example: Using sleep()


class SleepExample extends Thread {
public void run() {
for (int i = 1; i <= 5; i++) {
[Link]([Link]().getName() + " - " +
i);
try {
[Link](1000); // Suspend execution for 1 second
} catch (InterruptedException e) {
[Link]();
}
}
}

public static void main(String args[]) {


SleepExample t1 = new SleepExample();
SleepExample t2 = new SleepExample();

[Link]();
[Link]();
}
}

Output
Thread-0 - 1
Thread-1 - 1
Thread-0 - 2
Thread-1 - 2
...

The thread pauses execution for 1 second after printing each number.

7. Suspending and Resuming a Thread (Deprecated


Methods)
Java originally had suspend() and resume() methods, but they were deprecated due to
deadlock risks.

Example: Using suspend() (Deprecated)


class SuspendExample extends Thread {
public void run() {
for (int i = 1; i <= 5; i++) {
[Link]([Link]().getName() + " - " +
i);
}
}

public static void main(String args[]) {


SuspendExample t1 = new SuspendExample();
[Link]();
[Link](); // Suspends execution (Deprecated)
[Link]("Thread suspended...");
[Link](); // Resumes execution (Deprecated)
}
}

 suspend() and resume() can cause deadlocks and are not recommended.

8. Proper Way to Suspend and Resume Using wait() and


notify()

Instead of suspend(), Java recommends using wait() and notify().

Example: Using wait() and notify()


class WaitNotifyExample {
synchronized void printNumbers() {
for (int i = 1; i <= 5; i++) {
[Link]([Link]().getName() + " - " +
i);
try {
wait(); // Suspend execution
} catch (InterruptedException e) {
[Link]();
}
}
}

synchronized void resumeThread() {


notify(); // Resume execution
}

public static void main(String args[]) {


WaitNotifyExample obj = new WaitNotifyExample();

Thread t1 = new Thread(() -> [Link]());


Thread t2 = new Thread(() -> [Link]());
[Link]();
[Link]();
}
}

Explanation

 wait() suspends the thread until notify() is called.


 This prevents deadlocks and race conditions.

9. Summary
Feature Description
Synchronization Ensures that only one thread can access shared resources at a time.
Synchronized Methods The entire method is synchronized.
Synchronized Blocks Only a part of the method is synchronized for efficiency.
Locks (ReentrantLock) Provides more flexible locking mechanisms.
sleep(), wait(), and suspend() (deprecated) can pause
Thread Suspension
execution.
resume() (deprecated) or notify() (recommended) restarts
Thread Resumption
execution.

10. Best Practices


✔ Use synchronized blocks instead of synchronizing entire methods.
✔ Use ReentrantLock when more control is needed.
✔ Avoid suspend() and resume() (deprecated).
✔ Use wait() and notify() for controlled thread suspension.

Would you like me to cover thread deadlocks or inter-thread communication next? 🚀

Resuming and Stopping Threads in Java


1. Introduction
In Java, threads can be paused (suspended), resumed, and stopped using different
techniques. However, stopping a thread abruptly is unsafe, so Java provides safe ways to
terminate threads.

Deprecated Methods

 suspend(), resume(), and stop() methods of Thread class were deprecated due to
deadlocks and inconsistent states.
 Instead, we use flags (volatile variables), interrupts, and wait/notify mechanisms.
2. Resuming Threads in Java
Resuming a thread means allowing it to continue execution after being paused.

2.1 Using wait() and notify() (Preferred Method)

 wait() makes a thread wait until it is notified.


 notify() wakes up a waiting thread.

Example: Pausing and Resuming a Thread Using wait() and notify()


class ResumableThread {
private final Object lock = new Object();
private boolean isPaused = false;

void printNumbers() {
synchronized (lock) {
for (int i = 1; i <= 5; i++) {
while (isPaused) {
try {
[Link](); // Wait until notified
} catch (InterruptedException e) {
[Link]();
}
}
[Link]([Link]().getName() + " - "
+ i);
try {
[Link](500);
} catch (InterruptedException e) {
[Link]();
}
}
}
}

void pauseThread() {
synchronized (lock) {
isPaused = true;
}
}

void resumeThread() {
synchronized (lock) {
isPaused = false;
[Link](); // Notify waiting thread
}
}

public static void main(String[] args) {


ResumableThread obj = new ResumableThread();

Thread t1 = new Thread(() -> [Link]());


[Link]();
try {
[Link](1000);
[Link](); // Pause thread
[Link]("Thread Paused...");
[Link](2000);
[Link](); // Resume thread
[Link]("Thread Resumed...");
} catch (InterruptedException e) {
[Link]();
}
}
}

Output
Thread-0 - 1
Thread-0 - 2
Thread Paused...
Thread Resumed...
Thread-0 - 3
Thread-0 - 4
Thread-0 - 5

Explanation: The thread waits when pauseThread() is called and resumes when
resumeThread() is called.

3. Stopping a Thread in Java (Safe Methods)


Since [Link]() is deprecated, the recommended ways to stop a thread are:

1. Using a volatile boolean flag


2. Using interrupt() and checking isInterrupted()

3.1 Using a Volatile Flag (Preferred)

 A volatile boolean flag is used to signal the thread to stop safely.

Example: Stopping a Thread with a Volatile Flag

class StoppableThread extends Thread {


private volatile boolean running = true;

public void run() {


while (running) {
[Link]([Link]().getName() + " is
running...");
try {
[Link](1000);
} catch (InterruptedException e) {
[Link]();
}
}
[Link]([Link]().getName() + " stopped.");
}

public void stopThread() {


running = false;
}

public static void main(String[] args) {


StoppableThread t1 = new StoppableThread();
[Link]();

try {
[Link](5000);
} catch (InterruptedException e) {
[Link]();
}

[Link](); // Stop the thread


[Link]("Thread stop signal sent.");
}
}

Output
Thread-0 is running...
Thread-0 is running...
Thread-0 is running...
Thread-0 is running...
Thread-0 is running...
Thread stop signal sent.
Thread-0 stopped.

Explanation: The thread keeps running until running = false; is set.

3.2 Using interrupt() and isInterrupted()

 The interrupt() method does not stop the thread but sets an interrupted flag.
 The thread can check isInterrupted() and exit gracefully.

Example: Stopping a Thread Using interrupt()

class InterruptThread extends Thread {


public void run() {
while (![Link]().isInterrupted()) {
[Link]([Link]().getName() + " is
running...");
try {
[Link](1000);
} catch (InterruptedException e) {
[Link]([Link]().getName() + "
interrupted!");
break;
}
}
[Link]([Link]().getName() + " stopped.");
}
public static void main(String[] args) {
InterruptThread t1 = new InterruptThread();
[Link]();

try {
[Link](3000);
} catch (InterruptedException e) {
[Link]();
}

[Link](); // Send interrupt signal


[Link]("Thread interrupted signal sent.");
}
}

Output
Thread-0 is running...
Thread-0 is running...
Thread-0 is running...
Thread-0 interrupted!
Thread-0 stopped.
Thread interrupted signal sent.

Explanation: The interrupt() method sets the interrupt flag, and the thread checks for it
and exits gracefully.

4. Deprecated Methods (Do Not Use)


Method Status Reason
suspend()Deprecated Causes deadlocks
resume() Deprecated Unsafe if used with suspend()
stop() Deprecated Leaves shared resources inconsistent

Alternative Approaches: Use wait()/notify(), volatile flags, or interrupt() instead.

5. Summary
Feature Method Notes
Best practice for pausing and
Resuming Threads wait() & notify()
resuming threads.
Stopping Threads
Volatile boolean flag Simple and effective method.
(Safe)
Stopping Threads interrupt() & Useful when using blocking methods
(Alternative) isInterrupted() like sleep().
Deprecated Methods stop(), suspend(), Avoid using these due to deadlocks
Feature Method Notes
resume() and unsafe execution.

6. Best Practices
✔ Use volatile boolean or interrupt() for stopping threads safely.
✔ Use wait() and notify() instead of suspend() and resume().
✔ Never use stop(), suspend(), or resume() as they are deprecated.

Would you like me to cover thread communication techniques (such as producer-


consumer patterns) next? 🚀

I/O Streams in Java


1. Introduction to Java I/O Streams
Java provides a powerful Input/Output (I/O) API in the [Link] package, allowing data
transfer between different sources such as files, consoles, or network connections.

1.1 What Are Streams?

 A stream is a sequence of data (bytes or characters) that flows from a source to a


destination.
 Java defines two types of streams:
1. Input Stream → Reads data from a source.
2. Output Stream → Writes data to a destination.

1.2 Classification of Java Streams

Stream Type Description Example Classes


Handles raw binary InputStream, OutputStream, FileInputStream,
Byte Streams
data FileOutputStream
Character Handles textual data
Reader, Writer, FileReader, FileWriter
Streams (Unicode)

2. Byte Streams
Byte streams are used for handling binary data (images, audio, video, PDFs, etc.). They
work with 8-bit bytes.

2.1 Byte Input Stream (InputStream)

 Abstract superclass for reading binary data.


 Reads one byte at a time unless specified otherwise.
 Common subclasses:
o FileInputStream (reads from a file)
o ByteArrayInputStream (reads from a byte array)

Example: Reading a File Using FileInputStream

import [Link];
import [Link];

public class ByteStreamExample {


public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("[Link]")) {
int byteData;
while ((byteData = [Link]()) != -1) { // Read byte by byte
[Link]((char) byteData); // Convert byte to char
}
} catch (IOException e) {
[Link]();
}
}
}

Explanation: Reads a file byte-by-byte and converts it into characters.

2.2 Byte Output Stream (OutputStream)

 Abstract superclass for writing binary data.


 Writes one byte at a time unless specified otherwise.
 Common subclasses:
o FileOutputStream (writes to a file)
o ByteArrayOutputStream (writes to a byte array)

Example: Writing to a File Using FileOutputStream

import [Link];
import [Link];

public class ByteOutputStreamExample {


public static void main(String[] args) {
try (FileOutputStream fos = new FileOutputStream("[Link]")) {
String data = "Hello, Byte Streams!";
[Link]([Link]()); // Convert string to bytes
[Link]("Data written successfully.");
} catch (IOException e) {
[Link]();
}
}
}

Explanation: Converts a string to bytes and writes it to a file.


3. Character Streams
Character streams handle text data (Unicode characters). They work with 16-bit Unicode
characters, making them suitable for handling international text (like Hindi, Chinese,
etc.).

3.1 Character Input Stream (Reader)

 Abstract superclass for reading character data.


 Reads characters instead of bytes.
 Common subclasses:
o FileReader (reads from a file)
o BufferedReader (reads line by line)

Example: Reading a File Using FileReader

import [Link];
import [Link];

public class CharacterStreamExample {


public static void main(String[] args) {
try (FileReader fr = new FileReader("[Link]")) {
int charData;
while ((charData = [Link]()) != -1) { // Read character by
character
[Link]((char) charData);
}
} catch (IOException e) {
[Link]();
}
}
}

Explanation: Reads characters from a file instead of bytes.

3.2 Character Output Stream (Writer)

 Abstract superclass for writing character data.


 Writes characters instead of bytes.
 Common subclasses:
o FileWriter (writes to a file)
o BufferedWriter (writes line by line)

Example: Writing to a File Using FileWriter

import [Link];
import [Link];

public class CharacterOutputStreamExample {


public static void main(String[] args) {
try (FileWriter fw = new FileWriter("[Link]")) {
String data = "Hello, Character Streams!";
[Link](data);
[Link]("Data written successfully.");
} catch (IOException e) {
[Link]();
}
}
}

Explanation: Writes text directly to a file.

4. Difference Between Byte Streams and Character


Streams
Feature Byte Streams Character Streams
Base Classes InputStream / OutputStream Reader / Writer
Data Type Binary (8-bit bytes) Text (16-bit Unicode characters)
Use Cases Images, videos, audio, PDFs Text files, JSON, XML
Examples FileInputStream, FileOutputStream FileReader, FileWriter

5. Buffered Streams (Optimized I/O)


 Reading/writing one byte or character at a time is slow.
 Buffered Streams increase efficiency by reading/writing data in chunks.

Example: Using BufferedReader and BufferedWriter


import [Link].*;

public class BufferedExample {


public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new
FileReader("[Link]"));
BufferedWriter bw = new BufferedWriter(new
FileWriter("[Link]"))) {

String line;
while ((line = [Link]()) != null) { // Read line by line
[Link](line); // Write line by line
[Link](); // Add newline
}

[Link]("File copied successfully.");


} catch (IOException e) {
[Link]();
}
}
}
Explanation:
✔ [Link]() → Reads an entire line instead of a single character.
✔ [Link]() → Writes a newline to the file.

6. Summary
Stream Type Input Class Output Class Use Case
Byte Stream InputStream OutputStream Binary data (Images, Videos)
Character Stream Reader Writer Text files (Unicode support)
Buffered Streams BufferedReader BufferedWriter Faster text processing

7. Best Practices
✔ Use Buffered Streams (BufferedReader, BufferedWriter) for better performance.
✔ Use Character Streams (FileReader, FileWriter) for text processing.
✔ Use Byte Streams (FileInputStream, FileOutputStream) for binary files.
✔ Always close streams (try-with-resources is recommended).

Would you like me to cover Serialization and Deserialization next? 🚀

File Handling in Java


1. Introduction to File Handling
File handling in Java allows reading, writing, updating, and manipulating files stored on a
system. Java provides the [Link] and [Link] packages to perform file operations
efficiently.

1.1 Key Concepts

 A file is a collection of data stored on disk.


 Java treats files as streams of data.
 Common operations include:
o Creating files
o Writing to files
o Reading files
o Appending data
o Deleting files

2. File Handling Classes in Java


Java provides various classes for file handling:

Class Description
File Represents a file or directory path.
FileReader Reads characters from a file.
FileWriter Writes characters to a file.
BufferedReader Reads text from a file efficiently.
BufferedWriter Writes text to a file efficiently.
FileInputStream Reads binary data from a file.
FileOutputStream Writes binary data to a file.

3. Creating a File
To create a file, we use the File class.

Example: Creating a File


import [Link];
import [Link];

public class FileCreationExample {


public static void main(String[] args) {
try {
File file = new File("[Link]");
if ([Link]()) {
[Link]("File created: " + [Link]());
} else {
[Link]("File already exists.");
}
} catch (IOException e) {
[Link]("An error occurred.");
[Link]();
}
}
}

Explanation:
✔ createNewFile() method creates a new file.
✔ It returns true if the file is created successfully.
✔ If the file already exists, it returns false.

4. Writing to a File
To write data to a file, we use the FileWriter or BufferedWriter classes.

Example: Writing to a File Using FileWriter


import [Link];
import [Link];

public class FileWriteExample {


public static void main(String[] args) {
try (FileWriter writer = new FileWriter("[Link]")) {
[Link]("Hello, this is a file handling example in
Java.");
[Link]("Successfully written to the file.");
} catch (IOException e) {
[Link]();
}
}
}

Explanation:
✔ write() method writes data to the file.
✔ The file is automatically closed using try-with-resources.

Example: Writing to a File Using BufferedWriter


import [Link];
import [Link];
import [Link];

public class BufferedWriteExample {


public static void main(String[] args) {
try (BufferedWriter writer = new BufferedWriter(new
FileWriter("[Link]", true))) {
[Link]("\nAppending new content to the file.");
[Link]("Data appended successfully.");
} catch (IOException e) {
[Link]();
}
}
}

Explanation:
✔ BufferedWriter writes data efficiently.
✔ true in FileWriter("[Link]", true) enables append mode.

5. Reading from a File


To read data from a file, we use FileReader, BufferedReader, or Scanner.

Example: Reading a File Using FileReader


import [Link];
import [Link];

public class FileReadExample {


public static void main(String[] args) {
try (FileReader reader = new FileReader("[Link]")) {
int ch;
while ((ch = [Link]()) != -1) {
[Link]((char) ch);
}
} catch (IOException e) {
[Link]();
}
}
}

Explanation:
✔ Reads the file character by character.
✔ read() method returns -1 when the end of the file is reached.

Example: Reading a File Using BufferedReader (Line by Line)


import [Link];
import [Link];
import [Link];

public class BufferedReadExample {


public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new
FileReader("[Link]"))) {
String line;
while ((line = [Link]()) != null) {
[Link](line);
}
} catch (IOException e) {
[Link]();
}
}
}

Explanation:
✔ Reads the file line by line, making it more efficient.
✔ readLine() method reads an entire line at a time.

6. Appending Data to a File


Appending means adding new content to an existing file.

Example: Appending Data Using FileWriter


import [Link];
import [Link];

public class FileAppendExample {


public static void main(String[] args) {
try (FileWriter writer = new FileWriter("[Link]", true)) {
[Link]("\nThis is appended text.");
[Link]("Data appended successfully.");
} catch (IOException e) {
[Link]();
}
}
}

Explanation:
✔ Setting true in new FileWriter("[Link]", true) enables append mode.

7. Deleting a File
To delete a file, we use the delete() method of the File class.

Example: Deleting a File


import [Link];

public class FileDeleteExample {


public static void main(String[] args) {
File file = new File("[Link]");
if ([Link]()) {
[Link]("Deleted the file: " + [Link]());
} else {
[Link]("Failed to delete the file.");
}
}
}

Explanation:
✔ delete() method deletes the file and returns true if successful.

8. Checking File Information


The File class provides methods to check file properties.

Example: Getting File Information


import [Link];

public class FileInfoExample {


public static void main(String[] args) {
File file = new File("[Link]");
if ([Link]()) {
[Link]("File Name: " + [Link]());
[Link]("Absolute Path: " + [Link]());
[Link]("Writable: " + [Link]());
[Link]("Readable: " + [Link]());
[Link]("File Size: " + [Link]() + " bytes");
} else {
[Link]("The file does not exist.");
}
}
}

Explanation:
✔ exists() checks if the file exists.
✔ canRead() and canWrite() check permissions.
✔ length() returns file size in bytes.

9. Summary of File Handling Methods


Operation Method Class Used
Create a file createNewFile() File
FileWriter,
Write to a file write()
BufferedWriter
Read from a FileReader,
read(), readLine()
file BufferedReader
FileWriter,
Append data FileWriter("[Link]", true)
BufferedWriter
Delete a file delete() File

Check file info exists() , canRead(), canWrite(), File


length()

10. Best Practices


✔ Use BufferedReader & BufferedWriter for efficiency.
✔ Always close streams (use try-with-resources).
✔ Use append mode (true) carefully to avoid overwriting files.
✔ Check if a file exists (exists()) before performing operations.

Would you like me to cover serialization & deserialization next? 🚀

Exploring Various Java Packages: [Link],


[Link], [Link], etc.

1. Introduction to Java Packages


A package in Java is a collection of related classes and interfaces that help organize code
logically. Java provides built-in packages to handle various functionalities, including:

 Core language features ([Link])


 Data structures and utility classes ([Link])
 Regular expressions ([Link])
 File handling ([Link])
 Networking ([Link])
 Concurrency ([Link])

1.1 Why Use Packages?

✔ Code Organization: Helps maintain a clean project structure.


✔ Namespace Management: Avoids class name conflicts.
✔ Reusability: Provides a standard way to reuse code.
✔ Security: Protects access to certain classes using access modifiers.

2. [Link] Package (Fundamental Classes)


[Link] is the default package that is automatically imported in every Java program. It
contains essential classes such as Object, String, Math, System, Thread, and wrapper
classes.

2.1 Important Classes in [Link]

Class Description
Object The root class of all Java classes.
String Represents a sequence of characters.
StringBuilder Mutable string handling.
Math Provides mathematical functions.
System Provides system-level operations like input/output.
Thread Supports multithreading.
Runtime Allows interaction with the JVM.

2.2 Example: Using [Link] Classes


public class JavaLangExample {
public static void main(String[] args) {
// Using Math class
[Link]("Square Root of 16: " + [Link](16));

// Using String class


String text = "Java Programming";
[Link]("Uppercase: " + [Link]());

// Using System class


[Link]("Current Time: " + [Link]());
}
}

3. [Link] Package (Utility Classes)


The [Link] package provides data structures, date/time functions, collections
framework, random number generation, and more.
3.1 Important Classes in [Link]

Class Description
ArrayList Dynamic array implementation.
LinkedList Doubly linked list implementation.
HashMap Stores key-value pairs.
HashSet Collection of unique elements.
Date Represents date and time.
Calendar Provides date manipulation methods.
Random Generates random numbers.
Collections Utility class for collection operations.

3.2 Example: Using ArrayList and HashMap


import [Link];
import [Link];

public class JavaUtilExample {


public static void main(String[] args) {
// Using ArrayList
ArrayList<String> fruits = new ArrayList<>();
[Link]("Apple");
[Link]("Banana");
[Link]("Fruits List: " + fruits);

// Using HashMap
HashMap<Integer, String> studentMap = new HashMap<>();
[Link](101, "Alice");
[Link](102, "Bob");
[Link]("Student Map: " + studentMap);
}
}

4. [Link] Package (Regular Expressions)


The [Link] package allows pattern matching in strings using regular
expressions.

4.1 Important Classes in [Link]

Class Description
Pattern Defines a regex pattern.
Matcher Performs pattern matching on a string.
PatternSyntaxException Handles regex syntax errors.

4.2 Example: Validating Email Using Regex


import [Link].*;

public class RegexExample {


public static void main(String[] args) {
String email = "user@[Link]";
String regex = "^[A-Za-z0-9+_.-]+@(.+)$";

Pattern pattern = [Link](regex);


Matcher matcher = [Link](email);

if ([Link]()) {
[Link]("Valid Email!");
} else {
[Link]("Invalid Email!");
}
}
}

5. [Link] Package (File Handling and Input/Output)


The [Link] package handles reading and writing files, streams, and I/O operations.

5.1 Important Classes in [Link]

Class Description
File Represents a file or directory.
FileReader Reads data from a file.
FileWriter Writes data to a file.
BufferedReader Reads text from a file efficiently.
BufferedWriter Writes text to a file efficiently.

5.2 Example: Writing to a File


import [Link];
import [Link];

public class FileHandlingExample {


public static void main(String[] args) {
try (FileWriter writer = new FileWriter("[Link]")) {
[Link]("Hello, Java File Handling!");
[Link]("File Written Successfully.");
} catch (IOException e) {
[Link]();
}
}
}

6. [Link] Package (Networking)


The [Link] package supports network communication like HTTP, TCP, and UDP.

6.1 Important Classes in [Link]


Class Description
URL Represents a Uniform Resource Locator (URL).
URLConnection Establishes a connection to a URL.
Socket Implements TCP/IP socket connections.
ServerSocket Listens for incoming socket connections.

6.2 Example: Fetching Data from a URL


import [Link].*;

public class NetworkExample {


public static void main(String[] args) {
try {
URL url = new URL("[Link]
[Link]("Protocol: " + [Link]());
[Link]("Host: " + [Link]());
} catch (Exception e) {
[Link]();
}
}
}

7. [Link] Package (Multithreading and


Concurrency)
The [Link] package provides advanced multithreading utilities for
handling parallel execution.

7.1 Important Classes in [Link]

Class Description
ExecutorService Manages thread execution.
Future Represents the result of an asynchronous operation.
Semaphore Controls access to resources.
ConcurrentHashMap A thread-safe version of HashMap.

7.2 Example: Using ExecutorService for Multithreading


import [Link].*;

public class ConcurrentExample {


public static void main(String[] args) {
ExecutorService executor = [Link](3);

Runnable task = () -> [Link]("Task executed by: " +


[Link]().getName());

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


[Link](task);
}
[Link]();
}
}

8. Summary of Java Packages


Package Purpose
[Link] Core Java classes (String, Math, System, Object).
[Link] Collection framework, utilities, date/time.
[Link] Regular expressions.
[Link] File handling and input/output operations.
[Link] Networking and internet protocols.
[Link] Multithreading and concurrency.

Would you like more details on any specific package or concept? 🚀

MODULE – 4

Generics in Java (Templates)

Java Generics, introduced in Java 5, allow the creation of classes, interfaces, and methods
with type parameters. This enables code reusability and type safety while working with
different types of objects. Generics are similar to templates in C++ but with type erasure at
runtime.

1. Why Use Generics?


Generics help in:
✅ Type Safety – Ensures type correctness at compile time, reducing ClassCastException.
✅ Code Reusability – Generic classes and methods can be used for different data types.
✅ Elimination of Type Casting – No need for explicit type conversion.
✅ Improved Performance – Reduces runtime overhead caused by type casting.
Without Generics (Old Approach - Before Java 5)
import [Link].*;

public class WithoutGenerics {


public static void main(String[] args) {
List list = new ArrayList();
[Link]("Hello");
String s = (String) [Link](0); // Explicit type casting required
[Link](s);
}
}

Problems:

 Requires explicit type casting.


 Possible runtime errors if incorrect type is added.

2. Generic Classes
A generic class allows specifying a type parameter when creating an instance.

Syntax
class ClassName<T> {
// T represents the type parameter
}

Example: Generic Box Class


class Box<T> {
private T item;

public void setItem(T item) {


[Link] = item;
}

public T getItem() {
return item;
}
}

public class GenericClassExample {


public static void main(String[] args) {
Box<String> stringBox = new Box<>();
[Link]("Java Generics");
[Link]("Stored: " + [Link]());

Box<Integer> intBox = new Box<>();


[Link](100);
[Link]("Stored: " + [Link]());
}
}
Explanation:

 <T> is a placeholder for any type.


 The setItem method allows setting an item of type T, and getItem returns it.
 Instances of Box<String> and Box<Integer> use different data types without
casting.

3. Generic Methods
Generic methods allow defining a method with a generic type inside a non-generic or generic
class.

Syntax
<T> ReturnType methodName(T param) {
// method body
}

Example:
class Utility {
public static <T> void print(T value) {
[Link](value);
}
}

public class GenericMethodExample {


public static void main(String[] args) {
[Link]("Hello, Generics!");
[Link](123);
[Link](45.67);
}
}

Explanation:

 <T> before void makes the method generic.


 The method can accept any type and print it.

4. Generic Interfaces
Interfaces can also be generic.

Example
interface DataStore<T> {
void store(T item);
T retrieve();
}

class StringStore implements DataStore<String> {


private String data;

@Override
public void store(String item) {
[Link] = item;
}

@Override
public String retrieve() {
return data;
}
}

public class GenericInterfaceExample {


public static void main(String[] args) {
DataStore<String> stringData = new StringStore();
[Link]("Generic Interface Example");
[Link]([Link]());
}
}

5. Bounded Type Parameters


You can restrict the type parameter to a specific class or interface.

Syntax
<T extends SuperClass>

Example:
class NumberBox<T extends Number> {
private T num;

public NumberBox(T num) {


[Link] = num;
}

public double square() {


return [Link]() * [Link]();
}
}

public class BoundedTypeExample {


public static void main(String[] args) {
NumberBox<Integer> intBox = new NumberBox<>(5);
[Link]("Square: " + [Link]());

NumberBox<Double> doubleBox = new NumberBox<>(4.5);


[Link]("Square: " + [Link]());
}
}
Explanation:

 T extends Number ensures that only numeric types can be used.


 The square method uses doubleValue() to handle different number types.

6. Wildcards in Generics
Wildcards (?) allow flexibility when dealing with unknown types.

Types of Wildcards

1. Unbounded Wildcard <?>: Accepts any type.


2. Upper Bounded Wildcard <? extends T>: Accepts T or subclasses of T.
3. Lower Bounded Wildcard <? super T>: Accepts T or superclasses of T.

Example:
import [Link].*;

class WildcardExample {
public static void printList(List<?> list) {
for (Object item : list) {
[Link](item);
}
}

public static void main(String[] args) {


List<Integer> intList = [Link](1, 2, 3);
List<String> strList = [Link]("A", "B", "C");

printList(intList);
printList(strList);
}
}

Explanation:

 <?> means the method can accept List<Integer>, List<String>, or any other type.

7. Type Erasure
Java uses Type Erasure to remove generic type parameters at runtime.

Example
class Box<T> {
T item;
}
After compilation, it becomes:

class Box {
Object item;
}

 This ensures backward compatibility but means generic type information is lost at
runtime.

8. Generic vs Non-Generic Performance


Generics remove the need for casting, making them faster than using raw types.

Feature Generics Non-Generics


Type Safety ✅ Yes ❌ No
Code Reusability ✅ Yes ❌ No
Type Casting ❌ Not needed ✅ Required
Performance ✅ Faster ❌ Slower (due to casting)

9. Summary
 Generics improve type safety, reusability, and readability.
 Generic Classes, Methods, and Interfaces allow flexible programming.
 Bounded Types restrict generics to a specific class hierarchy.
 Wildcards (?, ? extends, ? super) provide more flexibility.
 Java Type Erasure removes generic parameters at runtime for backward
compatibility.

Would you like examples with more real-world applications, such as generic data structures
or database handling? 🚀

User-Defined Generic Classes in Java


A generic class in Java allows you to define a class with type parameters, enabling code
reusability while maintaining type safety.

1. Why Use User-Defined Generic Classes?


✅ Avoids code duplication by using a single class for multiple data types.
✅ Provides type safety at compile-time.
✅ Eliminates the need for explicit type casting.
✅ Improves code readability and maintainability.

2. Syntax of a Generic Class


A generic class is defined using angle brackets (<>) with a type parameter (T).

class ClassName<T> {
// Class body using T
}

 Tis a type parameter, which acts as a placeholder for actual data types.
 You can use multiple type parameters (T, U, V).
 Type parameter names are usually single uppercase letters:
o T → Type
o E → Element (used in collections)
o K, V → Key and Value (used in maps)

3. Example: A Simple Generic Class


This example demonstrates a Box class that can store any data type.

class Box<T> {
private T item;

// Constructor
public Box(T item) {
[Link] = item;
}

// Getter method
public T getItem() {
return item;
}

// Setter method
public void setItem(T item) {
[Link] = item;
}

// Displaying type of T
public void displayType() {
[Link]("Type of T: " + [Link]().getName());
}
}

public class GenericClassExample {


public static void main(String[] args) {
// Creating a Box for Strings
Box<String> stringBox = new Box<>("Hello, Java Generics!");
[Link]("Stored in String Box: " + [Link]());
[Link]();

// Creating a Box for Integers


Box<Integer> intBox = new Box<>(100);
[Link]("Stored in Integer Box: " + [Link]());
[Link]();
}
}

Output:
Stored in String Box: Hello, Java Generics!
Type of T: [Link]
Stored in Integer Box: 100
Type of T: [Link]

Explanation:

 Box<String> → Works with String values.


 Box<Integer> → Works with Integer values.
 The displayType() method prints the runtime type of T.

4. Generic Class with Multiple Type Parameters


You can define a class with multiple type parameters.

Example: A Pair Class with Two Generic Types


class Pair<K, V> {
private K key;
private V value;

// Constructor
public Pair(K key, V value) {
[Link] = key;
[Link] = value;
}

// Getter methods
public K getKey() {
return key;
}

public V getValue() {
return value;
}

// Display key-value pair


public void displayPair() {
[Link]("Key: " + key + " (" +
[Link]().getSimpleName() + "), " +
"Value: " + value + " (" +
[Link]().getSimpleName() + ")");
}
}

public class MultipleGenericExample {


public static void main(String[] args) {
Pair<String, Integer> student = new Pair<>("Alice", 95);
[Link]();

Pair<Integer, Double> product = new Pair<>(101, 79.99);


[Link]();
}
}

Output:
Key: Alice (String), Value: 95 (Integer)
Key: 101 (Integer), Value: 79.99 (Double)

Explanation:

 Pair<K, V> → Generic class with two type parameters.


 student stores String and Integer.
 product stores Integer and Double.

5. Bounded Type Parameters


You can restrict the generic type parameter to a specific class or interface using extends.

Syntax:
class ClassName<T extends SuperClass> {
// T must be a subclass of SuperClass
}

Example: Restricting T to Number Types


class NumberBox<T extends Number> {
private T num;

public NumberBox(T num) {


[Link] = num;
}

public double square() {


return [Link]() * [Link]();
}
}

public class BoundedGenericExample {


public static void main(String[] args) {
NumberBox<Integer> intBox = new NumberBox<>(5);
[Link]("Square: " + [Link]());
NumberBox<Double> doubleBox = new NumberBox<>(4.5);
[Link]("Square: " + [Link]());

// NumberBox<String> strBox = new NumberBox<>("Hello"); // ERROR:


String is not a subclass of Number
}
}

Output:
Square: 25.0
Square: 20.25

Explanation:

 <T extends Number> ensures T is a subclass of Number.


 Prevents usage of incompatible types like String.

6. Generic Class with Wildcards (?)


Wildcards allow flexibility when passing unknown generic types.

Example: Using <?> to Print Any Type of List


import [Link].*;

class WildcardExample {
public static void printList(List<?> list) {
for (Object item : list) {
[Link](item);
}
}

public static void main(String[] args) {


List<Integer> intList = [Link](10, 20, 30);
List<String> strList = [Link]("A", "B", "C");

printList(intList);
printList(strList);
}
}

Output:
10
20
30
A
B
C

Explanation:
 <?> → Allows any type of list.

7. Type Erasure in Generic Classes


At runtime, Java removes generic type information to maintain backward compatibility.

Example:
class GenericClass<T> {
T obj;
}

public class ErasureExample {


public static void main(String[] args) {
GenericClass<String> strObj = new GenericClass<>();
GenericClass<Integer> intObj = new GenericClass<>();

[Link]([Link]() == [Link]()); // TRUE


}
}

Output:
true

Explanation:

 After compilation, both GenericClass<String> and GenericClass<Integer>


become GenericClass.
 Type information is erased → getClass() returns the same class type.

8. Summary
✅ Generic classes allow type-safe, reusable, and efficient code.
✅ <T> represents a type parameter that is replaced with actual types at runtime.
✅ Multiple type parameters (<T, U>) can be used.
✅ Bounded types restrict generics to a specific class hierarchy (<T extends Number>).
✅ Wildcards (<?>) provide flexibility when passing different generic types.
✅ Type erasure removes generic type parameters at runtime.

9. Real-World Applications of Generic Classes


✅ Data Structures → Custom generic stacks, queues, and linked lists.
✅ Utility Classes → Generic sorting and filtering methods.
✅ Database Handling → Fetching different types of data dynamically.
✅ Frameworks & APIs → Java Collections (ArrayList<T>, HashMap<K, V>).

Would you like a custom example for a specific real-world use case? 🚀

[Link] Package in Java – A Complete Guide


The [Link] package is one of the most important and widely used packages in Java. It
provides utility classes for handling data structures, date and time, random numbers,
collections, and more.

1. Overview of [Link] Package


✅ Contains classes and interfaces for data structures (List, Set, Map, Queue).
✅ Provides date & time utilities.
✅ Supports random number generation.
✅ Includes utility classes for string manipulation, event handling, and more.

2. Key Classes and Interfaces in [Link]


The [Link] package contains various classes, grouped into different categories:

Category Key Classes & Interfaces


Collection Framework List, Set, Queue, Map
Date & Time Date, Calendar, TimeZone
Random Number Generation Random, SecureRandom
Utility Classes Objects, Arrays, Collections
Properties & Preferences Properties, ResourceBundle

3. Java Collections Framework ([Link])


The Collections Framework provides data structures like lists, sets, maps, and queues.

3.1 List Interface (Ordered Collection)


 Allows duplicate elements.
 Supports index-based access.
 Common implementations:
o ArrayList (dynamic array)
o LinkedList (doubly linked list)

Example: Using ArrayList


import [Link];

public class ListExample {


public static void main(String[] args) {
ArrayList<String> names = new ArrayList<>();
[Link]("Alice");
[Link]("Bob");
[Link]("Charlie");

[Link]("Names List: " + names);


[Link]("First Element: " + [Link](0));
}
}

Output:
Names List: [Alice, Bob, Charlie]
First Element: Alice

3.2 Set Interface (Unique Elements)


 Stores only unique elements.
 Does not maintain insertion order.
 Common implementations:
o HashSet (unordered, fastest)
o LinkedHashSet (maintains order)
o TreeSet (sorted order)

Example: Using HashSet


import [Link];

public class SetExample {


public static void main(String[] args) {
HashSet<Integer> numbers = new HashSet<>();
[Link](10);
[Link](20);
[Link](10); // Duplicate, will not be added

[Link]("HashSet: " + numbers);


}
}

Output:
HashSet: [10, 20]
3.3 Map Interface (Key-Value Pairs)
 Stores key-value pairs.
 Keys must be unique.
 Common implementations:
o HashMap (unordered, fast)
o LinkedHashMap (insertion order)
o TreeMap (sorted order)

Example: Using HashMap


import [Link];

public class MapExample {


public static void main(String[] args) {
HashMap<Integer, String> students = new HashMap<>();
[Link](101, "Alice");
[Link](102, "Bob");
[Link](103, "Charlie");

[Link]("Student Map: " + students);


[Link]("Student with ID 102: " + [Link](102));
}
}

Output:
Student Map: {101=Alice, 102=Bob, 103=Charlie}
Student with ID 102: Bob

4. Date & Time Utilities ([Link], Calendar)


Java provides classes to work with date and time.

4.1 Date Class (Old API)


import [Link];

public class DateExample {


public static void main(String[] args) {
Date currentDate = new Date();
[Link]("Current Date: " + currentDate);
}
}

Output:
Current Date: Wed Apr 03 10:15:30 IST 2025

4.2 Calendar Class


 Provides more flexibility than Date.
 Allows modification of date components.

import [Link];

public class CalendarExample {


public static void main(String[] args) {
Calendar calendar = [Link]();
[Link]("Current Year: " + [Link]([Link]));
[Link]("Current Month: " +
([Link]([Link]) + 1)); // 0-based index
}
}

Output:
Current Year: 2025
Current Month: 4

5. Random Number Generation ([Link])


Random class generates pseudo-random numbers.

import [Link];

public class RandomExample {


public static void main(String[] args) {
Random random = new Random();
[Link]("Random Number: " + [Link](100)); // 0-
99
}
}

Output:
Random Number: 45

6. Utility Classes in [Link]


6.1 Arrays Class
Used for array operations like sorting and searching.

import [Link];

public class ArraysExample {


public static void main(String[] args) {
int[] numbers = {5, 2, 9, 1, 3};
[Link](numbers);
[Link]("Sorted Array: " + [Link](numbers));
}
}

Output:
Sorted Array: [1, 2, 3, 5, 9]

6.2 Collections Class


Used for operations on collections like sorting and shuffling.

import [Link];
import [Link];

public class CollectionsExample {


public static void main(String[] args) {
ArrayList<String> names = new ArrayList<>();
[Link]("Alice");
[Link]("Bob");
[Link]("Charlie");

[Link](names);
[Link]("Shuffled List: " + names);
}
}

Output (varies due to shuffling):


Shuffled List: [Charlie, Alice, Bob]

7. Properties & Preferences (Properties Class)


Used to store key-value pairs in configuration files.

import [Link];

public class PropertiesExample {


public static void main(String[] args) {
Properties config = new Properties();
[Link]("username", "admin");
[Link]("password", "12345");

[Link]("Username: " + [Link]("username"));


}
}

Output:
Username: admin
8. Summary of [Link] Package
Feature Key Classes/Interfaces
Collections List, Set, Map, Queue
Date & Time Date, Calendar, TimeZone
Random Number Random, SecureRandom
Utilities Arrays, Collections, Objects
Properties Properties, ResourceBundle

9. Real-World Applications
✅ Data Processing – Storing and retrieving structured data (e.g., employee records).
✅ Sorting & Searching – Optimized operations on large datasets.
✅ Configuration Management – Reading app settings from Properties files.
✅ Cryptography – SecureRandom for secure number generation.

Do you need a detailed explanation of any specific class from [Link]? 🚀

Java Collection Framework – A Complete


Guide
The Java Collection Framework (JCF) is a set of classes and interfaces that provide
efficient data structures to store, manipulate, and process data.

1. Overview of Java Collection Framework


✅ Introduced in Java 2 (JDK 1.2).
✅ Provides ready-made data structures like List, Set, Queue, and Map.
✅ Supports dynamic memory allocation and generic programming.
✅ Includes utility methods for sorting, searching, and modifying collections.

2. Key Interfaces in Java Collection


Framework
Interface Description Common Implementations
Ordered collection (allows
List ArrayList, LinkedList, Vector
duplicates).
Interface Description Common Implementations
Stores unique elements (no
Set HashSet, LinkedHashSet, TreeSet
duplicates).
Queue Follows FIFO (First In, First Out). PriorityQueue, ArrayDeque
Stores key-value pairs (no duplicate HashMap, LinkedHashMap, TreeMap,
Map
keys). Hashtable

🔹 List, Set, and Queue extend the Collection interface, while Map is a separate hierarchy.

3. Hierarchy of Java Collection Framework


Collection (Interface)

┌──────────┴───────────┐
List Set Queue
│ │ │
ArrayList HashSet PriorityQueue
LinkedList LinkedHashSet ArrayDeque
Vector TreeSet

 Map is separate from Collection but is part of the framework.

4. List Interface (Ordered Collection with


Duplicates)
 Allows index-based access.
 Maintains insertion order.
 Can contain duplicate elements.

4.1 ArrayList (Resizable Array)


✅ Fast read operations (O(1) access time).
✅ Slower insert/delete (O(n) in the middle).

Example: Using ArrayList


import [Link];

public class ArrayListExample {


public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
[Link]("Apple");
[Link]("Banana");
[Link]("Cherry");
[Link]("ArrayList: " + list);
[Link]("Element at index 1: " + [Link](1));
}
}

Output
ArrayList: [Apple, Banana, Cherry]
Element at index 1: Banana

4.2 LinkedList (Doubly Linked List)


✅ Fast insert/delete (O(1) at the head/tail).
✅ Slower access (O(n) traversal).

import [Link];

public class LinkedListExample {


public static void main(String[] args) {
LinkedList<Integer> numbers = new LinkedList<>();
[Link](10);
[Link](20);
[Link](5);
[Link](30);

[Link]("LinkedList: " + numbers);


}
}

Output
LinkedList: [5, 10, 20, 30]

5. Set Interface (Unique Elements)


 No duplicate elements allowed.
 Does not maintain order (except LinkedHashSet and TreeSet).

5.1 HashSet (Unordered, Fast)


✅ Fast operations (O(1) average time).
✅ No guarantee of order.

import [Link];

public class HashSetExample {


public static void main(String[] args) {
HashSet<String> fruits = new HashSet<>();
[Link]("Apple");
[Link]("Banana");
[Link]("Apple"); // Duplicate ignored
[Link]("HashSet: " + fruits);
}
}

Output
HashSet: [Banana, Apple] // Order may vary

5.2 TreeSet (Sorted Order)


✅ Stores elements in sorted order.
✅ Uses Red-Black tree (O(log n) operations).

import [Link];

public class TreeSetExample {


public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
[Link](50);
[Link](10);
[Link](30);

[Link]("TreeSet: " + numbers);


}
}

Output
TreeSet: [10, 30, 50] // Sorted

6. Queue Interface (FIFO Structure)


 Follows First-In-First-Out (FIFO).
 Used in task scheduling, message processing.

6.1 PriorityQueue (Heap-based, Ordered)


✅ Elements retrieved in sorted order.
✅ Not thread-safe.

import [Link];

public class PriorityQueueExample {


public static void main(String[] args) {
PriorityQueue<Integer> queue = new PriorityQueue<>();
[Link](30);
[Link](10);
[Link](20);

[Link]("PriorityQueue: " + queue);


[Link]("Head Element: " + [Link]()); // Removes
smallest element
}
}

Output
PriorityQueue: [10, 30, 20] // Internal structure may differ
Head Element: 10

7. Map Interface (Key-Value Pairs)


 Stores unique keys with mapped values.

7.1 HashMap (Fast, Unordered)


✅ Fast lookups (O(1) on average).
✅ Unordered storage.

import [Link];

public class HashMapExample {


public static void main(String[] args) {
HashMap<Integer, String> students = new HashMap<>();
[Link](101, "Alice");
[Link](102, "Bob");

[Link]("Student Map: " + students);


[Link]("Student with ID 101: " + [Link](101));
}
}

Output
Student Map: {101=Alice, 102=Bob}
Student with ID 101: Alice

8. Utility Methods in Collections Class


✅ Sorting a List

import [Link];
import [Link];

public class CollectionsExample {


public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<>();
[Link](30);
[Link](10);
[Link](20);

[Link](numbers);
[Link]("Sorted List: " + numbers);
}
}

Output
Sorted List: [10, 20, 30]

✅ Finding Maximum & Minimum

[Link]("Max: " + [Link](numbers));


[Link]("Min: " + [Link](numbers));

✅ Shuffling a List

[Link](numbers);
[Link]("Shuffled List: " + numbers);

9. Summary of Collection Framework


Interface Key Implementations Features
List ArrayList, LinkedList Ordered, Duplicates Allowed
Set HashSet, TreeSet Unique Elements
Queue PriorityQueue, ArrayDeque FIFO, Ordered
Map HashMap, TreeMap Key-Value Pairs

🔹 List is best for indexed access, Set for uniqueness, Queue for FIFO, and Map for key-
value pairs.

Would you like detailed notes on any specific collection type? 🚀

List, Set, and Map Interfaces in Java


Collection Framework
Java provides various collection interfaces to store and manage data efficiently. The three
most commonly used interfaces are:

1. List – Ordered collection allowing duplicates.


2. Set – Unordered collection that ensures uniqueness.
3. Map – Key-value pairs, where keys are unique.

1. List Interface (Ordered Collection, Allows Duplicates)


🔹 Features of List
✔ Maintains insertion order.
✔ Allows duplicate elements.
✔ Supports index-based access (get(index)).

1.1 Implementations of List

Implementation Underlying Structure Performance Characteristics


ArrayList Dynamic array Fast read, slow insert/delete
LinkedList Doubly linked list Fast insert/delete, slow access
Vector Thread-safe dynamic array Synchronized (slower than ArrayList)

1.2 ArrayList Example


import [Link];

public class ArrayListExample {


public static void main(String[] args) {
ArrayList<String> names = new ArrayList<>();
[Link]("Alice");
[Link]("Bob");
[Link]("Charlie");

[Link]("ArrayList: " + names);


[Link]("Element at index 1: " + [Link](1));
}
}

✅ Output

ArrayList: [Alice, Bob, Charlie]


Element at index 1: Bob

1.3 LinkedList Example


import [Link];

public class LinkedListExample {


public static void main(String[] args) {
LinkedList<Integer> numbers = new LinkedList<>();
[Link](10);
[Link](20);
[Link](5);
[Link](30);

[Link]("LinkedList: " + numbers);


}
}

✅ Output

LinkedList: [5, 10, 20, 30]


1.4 Vector Example
import [Link];

public class VectorExample {


public static void main(String[] args) {
Vector<Double> v = new Vector<>();
[Link](2.5);
[Link](3.6);
[Link](4.7);

[Link]("Vector: " + v);


}
}

✅ Output

Vector: [2.5, 3.6, 4.7]

2. Set Interface (No Duplicates, Unordered)


🔹 Features of Set
✔ Does not allow duplicate elements.
✔ Does not maintain insertion order (except LinkedHashSet).
✔ TreeSet maintains elements in sorted order.

2.1 Implementations of Set

Implementation Underlying Structure Performance Characteristics


HashSet Hash table Fast (O(1) add/remove) but unordered
LinkedHashSet Hash table + Linked List Maintains insertion order
TreeSet Red-Black tree Elements sorted, O(log n) operations

2.2 HashSet Example


import [Link];

public class HashSetExample {


public static void main(String[] args) {
HashSet<String> fruits = new HashSet<>();
[Link]("Apple");
[Link]("Banana");
[Link]("Apple"); // Duplicate ignored

[Link]("HashSet: " + fruits);


}
}

✅ Output (Order may vary)


HashSet: [Banana, Apple]

2.3 LinkedHashSet Example


import [Link];

public class LinkedHashSetExample {


public static void main(String[] args) {
LinkedHashSet<Integer> numbers = new LinkedHashSet<>();
[Link](30);
[Link](10);
[Link](20);

[Link]("LinkedHashSet: " + numbers);


}
}

✅ Output

LinkedHashSet: [30, 10, 20] // Maintains insertion order

2.4 TreeSet Example


import [Link];

public class TreeSetExample {


public static void main(String[] args) {
TreeSet<Integer> sortedNumbers = new TreeSet<>();
[Link](50);
[Link](10);
[Link](30);

[Link]("TreeSet: " + sortedNumbers);


}
}

✅ Output

TreeSet: [10, 30, 50] // Sorted order

3. Map Interface (Key-Value Pairs)


🔹 Features of Map
✔ Stores key-value pairs.
✔ Keys must be unique, but values can be duplicated.
✔ Does not extend Collection.

3.1 Implementations of Map


Implementation Underlying Structure Performance Characteristics
HashMap Hash table Fast (O(1) lookups), unordered
LinkedHashMap Hash table + Linked List Maintains insertion order
TreeMap Red-Black tree Keys sorted, O(log n) operations

3.2 HashMap Example


import [Link];

public class HashMapExample {


public static void main(String[] args) {
HashMap<Integer, String> students = new HashMap<>();
[Link](101, "Alice");
[Link](102, "Bob");

[Link]("Student Map: " + students);


[Link]("Student with ID 101: " + [Link](101));
}
}

✅ Output

Student Map: {101=Alice, 102=Bob}


Student with ID 101: Alice

3.3 LinkedHashMap Example


import [Link];

public class LinkedHashMapExample {


public static void main(String[] args) {
LinkedHashMap<String, Integer> scores = new LinkedHashMap<>();
[Link]("Alice", 85);
[Link]("Bob", 90);
[Link]("Charlie", 78);

[Link]("LinkedHashMap: " + scores);


}
}

✅ Output

LinkedHashMap: {Alice=85, Bob=90, Charlie=78} // Maintains insertion order

3.4 TreeMap Example


import [Link];

public class TreeMapExample {


public static void main(String[] args) {
TreeMap<Integer, String> employees = new TreeMap<>();
[Link](102, "Bob");
[Link](101, "Alice");
[Link](103, "Charlie");

[Link]("TreeMap: " + employees);


}
}

✅ Output

TreeMap: {101=Alice, 102=Bob, 103=Charlie} // Sorted order

4. Summary Table
Allows Common
Interface Maintains Order?
Duplicates? Implementations
ArrayList,
List ✅ Yes ✅ Yes
LinkedList, Vector
❌ No (HashSet), ✅ Yes HashSet,
Set ❌ No (LinkedHashSet), ✅ Sorted LinkedHashSet,
(TreeSet) TreeSet
❌ No (HashMap), ✅ Yes HashMap,
❌ No (Keys), ✅ Yes
Map (LinkedHashMap), ✅ Sorted LinkedHashMap,
(Values)
(TreeMap) TreeMap

Would you like me to cover advanced concepts like synchronization, performance


comparison, or concurrent collections? 🚀

Vector, ArrayList, Stack, Queue, and


LinkedList in Java
The Java Collection Framework (JCF) provides several classes for handling dynamic data
structures. Among these, Vector, ArrayList, Stack, Queue, and LinkedList are commonly
used for storing and processing ordered collections of elements. Each class has unique
characteristics and performance trade-offs.

1. ArrayList (Dynamic Array Implementation)


🔹 ArrayList is a resizable array implementation of the List interface.

Key Features

✔ Maintains insertion order.


✔ Allows duplicate elements.
✔ Supports random access (get(index)) in O(1) time.
✔ Not synchronized (not thread-safe).

1.1 ArrayList Example


import [Link];

public class ArrayListExample {


public static void main(String[] args) {
ArrayList<String> names = new ArrayList<>();
[Link]("Alice");
[Link]("Bob");
[Link]("Charlie");
[Link]("Alice"); // Allows duplicate elements

[Link]("ArrayList: " + names);


[Link]("Element at index 1: " + [Link](1));
}
}

✅ Output

ArrayList: [Alice, Bob, Charlie, Alice]


Element at index 1: Bob

1.2 When to Use ArrayList?

✔ When random access is required frequently.


✔ When the order of insertion matters.
✔ When thread safety is not needed.

2. Vector (Thread-Safe Dynamic Array)


🔹 Vector is similar to ArrayList but is synchronized, making it thread-safe.

Key Features

✔ Thread-safe, synchronized methods.


✔ Slower than ArrayList due to synchronization.
✔ Supports random access (get(index)) in O(1) time.

2.1 Vector Example


import [Link];

public class VectorExample {


public static void main(String[] args) {
Vector<Integer> numbers = new Vector<>();
[Link](10);
[Link](20);
[Link](30);
[Link]("Vector: " + numbers);
[Link]("Element at index 1: " + [Link](1));
}
}

✅ Output

Vector: [10, 20, 30]


Element at index 1: 20

2.2 When to Use Vector?

✔ When thread safety is required.


✔ When concurrent modifications are needed.

3. Stack (LIFO - Last In, First Out)


🔹 Stack is a subclass of Vector and follows LIFO (Last-In-First-Out) principle.

Key Features

✔ push() to add elements.


✔ pop() to remove the top element.
✔ peek() to view the top element without removing it.
✔ isEmpty() to check if the stack is empty.

3.1 Stack Example


import [Link];

public class StackExample {


public static void main(String[] args) {
Stack<String> books = new Stack<>();
[Link]("Java Programming");
[Link]("Data Structures");
[Link]("Algorithms");

[Link]("Stack: " + books);


[Link]("Top element: " + [Link]());
[Link]("Popped element: " + [Link]());
[Link]("Stack after pop: " + books);
}
}

✅ Output

Stack: [Java Programming, Data Structures, Algorithms]


Top element: Algorithms
Popped element: Algorithms
Stack after pop: [Java Programming, Data Structures]
3.2 When to Use Stack?

✔ When LIFO (Last-In-First-Out) operations are required.


✔ Example use cases: Undo/Redo functionality, Expression evaluation, DFS traversal.

4. Queue (FIFO - First In, First Out)


🔹 Queue follows FIFO (First-In-First-Out) principle.
🔹 Implemented using LinkedList or PriorityQueue.

Key Features

✔ add(element) or offer(element) to insert elements.


✔ remove() or poll() to remove elements.
✔ peek() to view the front element without removing it.

4.1 Queue Example (Using LinkedList)


import [Link];
import [Link];

public class QueueExample {


public static void main(String[] args) {
Queue<Integer> queue = new LinkedList<>();
[Link](1);
[Link](2);
[Link](3);

[Link]("Queue: " + queue);


[Link]("Front element: " + [Link]());
[Link]("Removed element: " + [Link]());
[Link]("Queue after removal: " + queue);
}
}

✅ Output

Queue: [1, 2, 3]
Front element: 1
Removed element: 1
Queue after removal: [2, 3]

4.2 When to Use Queue?

✔ When FIFO (First-In-First-Out) processing is required.


✔ Example use cases: Task scheduling, CPU scheduling, Printer queue.

5. LinkedList (Doubly Linked List)


🔹 LinkedList is a doubly linked list implementation of both List and Queue.

Key Features

✔ Efficient insertions and deletions (O(1) at beginning/end).


✔ Slower access time (O(n)) compared to ArrayList.
✔ Implements both List and Queue interfaces.

5.1 LinkedList as a List


import [Link];

public class LinkedListExample {


public static void main(String[] args) {
LinkedList<String> names = new LinkedList<>();
[Link]("Alice");
[Link]("Bob");
[Link]("Zara");
[Link]("Charlie");

[Link]("LinkedList: " + names);


}
}

✅ Output

LinkedList: [Zara, Alice, Bob, Charlie]

5.2 When to Use LinkedList?

✔ When frequent insertions/deletions are required.


✔ When implementing Queue or Deque operations.

6. Summary Table
Underlying Access Order Thread
Class Insertion
Structure Time Maintained? Safety
Slow
ArrayList Dynamic array Fast (O(1)) ✅ Yes ❌ No
(O(n))
Slow
Vector Dynamic array Fast (O(1)) ✅ Yes ✅ Yes
(O(n))
Dynamic array
Stack Fast (O(1)) Fast (O(1)) ✅ Yes ✅ Yes
(LIFO)
Slow
Queue Linked list (FIFO) Fast (O(1)) ✅ Yes ❌ No
(O(n))
Slow
LinkedList Doubly linked list Fast (O(1)) ✅ Yes ❌ No
(O(n))
7. Choosing the Right Data Structure
✔ Use ArrayList when frequent random access is needed.
✔ Use Vector when thread safety is required.
✔ Use Stack for LIFO operations.
✔ Use Queue for FIFO processing.
✔ Use LinkedList when frequent insertions and deletions are required.

Would you like me to cover priority queues, deques, or concurrent collections next? 🚀

MODULE – 5

Java Annotations and Its Types

1. Introduction to Java Annotations

Java Annotations are metadata that provide additional information about the program without
affecting its execution. They are used to give instructions to the compiler, runtime
environment, or tools. Introduced in Java 5 (JDK 1.5), annotations help in code readability,
testing, and reducing boilerplate code.

Annotations can be used for:

 Compilation-time instructions (e.g., @Override, @Deprecated)


 Runtime processing (e.g., @Retention, @Target)
 Code generation using frameworks like Spring, Hibernate, Lombok, and JUnit

2. Syntax of Annotations

Annotations are defined using the @ symbol, followed by the annotation name.
Example:

@Override
public void display() {
[Link]("Overridden method");
}

Here, @Override tells the compiler that the method is overriding a superclass method.

3. Types of Annotations in Java

Annotations in Java can be classified into the following categories:

A. Built-in Java Annotations


Java provides several predefined annotations, mainly used for compiler instructions and code
readability.

1. @Override
o Used to indicate that a method overrides a superclass method.
o Helps in avoiding errors if the method signature changes.
2. class Parent {
3. void show() {
4. [Link]("Parent class method");
5. }
6. }
7.
8. class Child extends Parent {
9. @Override
10. void show() {
11. [Link]("Overridden method in Child class");
12. }
13. }
14. @Deprecated
o Marks a method or class as outdated, discouraging its use.
o Generates a warning if used.
15. @Deprecated
16. public void oldMethod() {
17. [Link]("This method is deprecated");
18. }
19. @SuppressWarnings
o Suppresses compiler warnings for a specific piece of code.
o Common values: unchecked, deprecated, unused
20. @SuppressWarnings("unchecked")
21. List myList = new ArrayList();
22. @FunctionalInterface (Java 8)
o Ensures an interface has exactly one abstract method, making it a functional
interface.
23. @FunctionalInterface
24. interface MyInterface {
25. void myMethod();
26. }
27. @SafeVarargs (Java 7)
o Prevents heap pollution warnings when working with varargs and generics.
28. @SafeVarargs
29. private void display(String... messages) {
30. for (String msg : messages) {
31. [Link](msg);
32. }
33. }
34. @Native (Java 8)
o Indicates constants that are meant for native code use.
35. public class Constants {
36. @Native
37. public static final int ERROR_CODE = 1;
38. }

B. Meta-Annotations (Annotations for Annotations)


Java provides meta-annotations, which are annotations applied to other annotations to
control their behavior.

1. @Retention
o Specifies how long an annotation is retained.
o Values:
 SOURCE – Discarded during compilation.
 CLASS – Available in the class file but not at runtime.
 RUNTIME – Available at runtime via reflection.
2. @Retention([Link])
3. @interface MyAnnotation {
4. String value();
5. }
6. @Target
o Specifies where an annotation can be applied.
o Values: TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE
7. @Target([Link])
8. @interface MethodAnnotation {}
9. @Documented
o Indicates that an annotation should be included in Javadoc.
10. @Documented
11. @interface APIInfo {
12. String author();
13. }
14. @Inherited
o Allows an annotation to be inherited by subclasses.
15. @Inherited
16. @interface Inheritable {}

C. Custom Annotations

We can define our own annotations using the @interface keyword.

Example:

import [Link].*;

@Retention([Link])
@Target([Link])
@interface MyAnnotation {
String author() default "Unknown";
int version() default 1;
}

class Demo {
@MyAnnotation(author = "Alice", version = 2)
public void display() {
[Link]("Custom annotation example");
}
}

D. Java Annotations in Popular Frameworks


Annotations are widely used in frameworks like Spring, Hibernate, JUnit, and Lombok.

1. Spring Annotations
o @Component, @Service, @Repository – Define Spring-managed beans.
o @Autowired – Injects dependencies.
o @RestController, @RequestMapping – Used in REST APIs.
2. Hibernate Annotations
o @Entity, @Table, @Column – Define database mappings.
o @Id, @GeneratedValue – Define primary key generation.
3. JUnit Annotations
o @Test – Marks a method as a test case.
o @BeforeEach, @AfterEach – Run before/after each test.
4. Lombok Annotations
o @Getter, @Setter – Auto-generate getters/setters.
o @ToString, @EqualsAndHashCode – Reduce boilerplate code.

4. Reflection and Runtime Processing of Annotations

Annotations can be accessed at runtime using Java Reflection API.

Example:

import [Link].*;
import [Link];

@Retention([Link])
@Target([Link])
@interface MyCustomAnnotation {
String value();
}

class Example {
@MyCustomAnnotation(value = "Hello, Annotation!")
public void myMethod() {}
}

public class AnnotationProcessor {


public static void main(String[] args) throws Exception {
Method method = [Link]("myMethod");
MyCustomAnnotation annotation =
[Link]([Link]);
[Link]("Annotation Value: " + [Link]());
}
}

Output:

Annotation Value: Hello, Annotation!

5. Summary
Annotation Type Description
Built-in @Override, @Deprecated, @SuppressWarnings,
Annotations @FunctionalInterface, @SafeVarargs, @Native
Meta-Annotations @Retention, @Target, @Documented, @Inherited
Custom
User-defined annotations using @interface
Annotations
Framework
Used in Spring, Hibernate, JUnit, Lombok, etc.
Annotations
Runtime Processing Accessed using Reflection API

6. Conclusion

Java Annotations are a powerful feature that simplifies code, improves readability, and helps
in runtime processing. They play a crucial role in modern frameworks, making Java
applications more efficient and maintainable.

Would you like detailed notes on any specific framework-related annotations?

Creating Custom Annotations in Java

Java allows us to create our own annotations using the @interface keyword. Custom
annotations help define metadata for classes, methods, fields, or parameters, which can then
be processed using reflection.

1. Defining a Custom Annotation


A custom annotation is defined using the @interface keyword. It can have elements
(methods) with default values.

Example of a Simple Custom Annotation


@interface MyAnnotation {
String value(); // Element without default value
}

 Here, value() is an annotation element (like a method).


 When applied, we must provide a value, e.g., @MyAnnotation("Test").

2. Adding Elements to an Annotation


Elements in an annotation resemble method declarations but cannot have parameters or throw
exceptions.
Example with Multiple Elements
@interface MyAnnotation {
String author();
int version() default 1; // Default value provided
}

 author() requires a mandatory value.


 version() has a default value, so it can be omitted when used.

Usage
@MyAnnotation(author = "Alice", version = 2)
public class MyClass {
// Class body
}

3. Applying Meta-Annotations
Meta-annotations modify the behavior of annotations. The commonly used ones are:

@Retention (Retention Policy)

Defines how long the annotation is retained:

 SOURCE – Discarded during compilation.


 CLASS – Retained in class file but not available at runtime.
 RUNTIME – Available at runtime for reflection.

Example

import [Link];
import [Link];

@Retention([Link]) // Available at runtime


@interface Info {
String author();
String date();
}

@Target (Annotation Usage Restrictions)

Defines where the annotation can be applied:

 [Link] – Class, interface, or enum.


 [Link] – Methods.
 [Link] – Fields.
 [Link] – Method parameters.
 [Link] – Constructors.
Example

import [Link];
import [Link];

@Target([Link]) // Can only be applied to methods


@interface Loggable {
}

@Documented (Include in Javadoc)

Used to include annotations in Javadoc documentation.

import [Link];

@Documented
@interface APIInfo {
String author();
String version();
}

@Inherited (Annotation Inheritance)

Allows annotations to be inherited by subclasses.

import [Link];

@Inherited
@interface InheritableAnnotation {
}

 If a class is annotated, its subclasses inherit the annotation.

4. Using Reflection to Process Custom Annotations


Annotations can be accessed at runtime using Java Reflection API.

Example
import [Link];
import [Link];
import [Link];

// Define annotation
@Retention([Link])
@interface MyAnnotation {
String value();
}

// Apply annotation
class Demo {
@MyAnnotation(value = "Hello, Annotation!")
public void display() {
[Link]("Display method");
}
}

// Process annotation using Reflection


public class AnnotationProcessor {
public static void main(String[] args) throws Exception {
Method method = [Link]("display");
MyAnnotation annotation = [Link]([Link]);
[Link]("Annotation Value: " + [Link]());
}
}

Output:

Annotation Value: Hello, Annotation!

5. Real-World Use Cases of Custom Annotations


1. Logging Method Calls
2. @Target([Link])
3. @Retention([Link])
4. @interface LogExecution {
5. }
6.
7. class Test {
8. @LogExecution
9. public void testMethod() {
10. [Link]("Executing method...");
11. }
12. }

The annotation could be processed at runtime to log method execution.

13. Marking Important API Methods


14. @Documented
15. @Retention([Link])
16. @Target([Link])
17. public @interface ImportantAPI {
18. String value();
19. }
o Helps developers know which API methods are critical.
20. Framework-Specific Annotations
o Spring uses annotations like @Component, @Service, @Repository for
dependency injection.
o Hibernate uses @Entity, @Table, @Column for ORM mapping.

6. Summary
Feature Description
@interface Defines a custom annotation.
@Retention Specifies how long the annotation is retained (SOURCE, CLASS, RUNTIME).
@Target Specifies where the annotation can be applied (Class, Method, Field, etc.).
@Documented Makes the annotation appear in Javadoc.
@Inherited Allows the annotation to be inherited by subclasses.
Reflection API Used to process annotations at runtime.

Conclusion

Custom annotations in Java provide a powerful way to add metadata, automate tasks, and
improve code readability. They are extensively used in frameworks like Spring, Hibernate,
JUnit, and Lombok.

Would you like a more detailed example on any specific use case? 😊

Maven Framework – A Detailed Guide


1. Introduction to Maven
Maven is a powerful build automation and project management tool used primarily for
Java projects. It simplifies project builds, dependency management, and project lifecycle
management.

Key Features of Maven

✅ Build Automation – Automates compiling, testing, packaging, and deploying.


✅ Dependency Management – Automatically downloads required libraries from
repositories.
✅ Project Structure Standardization – Provides a consistent project structure.
✅ Convention over Configuration – Reduces configuration overhead by following
predefined rules.
✅ Multi-Module Support – Supports building multiple related projects together.
✅ Integration with IDEs – Works seamlessly with Eclipse, IntelliJ IDEA, and VS Code.

2. Installing Maven
Maven requires Java JDK 8 or higher.

Steps to Install Maven:

1. Download Maven from Apache Maven Official Website.


2. Extract and Set Environment Variables (MAVEN_HOME and PATH).
3. Verify Installation: Run:
4. mvn -version

Output should display the installed Maven version.

3. Maven Project Structure


A Maven project follows a standard directory structure:

my-maven-project
│── src
│ ├── main
│ │ ├── java (Source code)
│ │ ├── resources (Config files)
│ ├── test
│ │ ├── java (Test cases)
│ │ ├── resources (Test config files)
│── [Link] (Maven configuration)
│── target (Compiled output)
│── .mvn (Maven wrapper)

4. Creating a Maven Project


Using Command Line

Run:

mvn archetype:generate -DgroupId=[Link] -DartifactId=my-app -


DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

🔹 groupId – Package name (e.g., [Link]).


🔹 artifactId – Project name (my-app).
🔹 archetypeArtifactId – Template used to generate the project.

Using IntelliJ IDEA / Eclipse

1. File → New → Project → Maven.


2. Select Project SDK (JDK 8+).
3. Enter GroupId, ArtifactId, and Package Name.
4. Finish.

5. Understanding [Link] (Project Object Model)


[Link] is the core configuration file in a Maven project.
Basic [Link] Structure
<project xmlns="[Link]
xmlns:xsi="[Link]
xsi:schemaLocation="[Link]
[Link]
<modelVersion>4.0.0</modelVersion>

<groupId>[Link]</groupId>
<artifactId>my-app</artifactId>
<version>1.0.0</version>

<dependencies>
<!-- Example Dependency -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

🔹 groupId – Unique identifier for the project (e.g., [Link]).


🔹 artifactId – Project name (e.g., my-app).
🔹 version – Project version (1.0.0).
🔹 dependencies – External libraries required for the project.

6. Dependency Management in Maven


Maven automatically downloads dependencies from Maven Central Repository.

Adding a Dependency

Example: Adding JUnit for testing.

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

🔹 scope values:

 compile – Default, used at compile time.


 test – Used for testing only.
 runtime – Available at runtime but not at compile time.
 provided – Needed for compilation but not included in the final package.

Viewing Dependencies
Run:

mvn dependency:tree

7. Maven Build Lifecycle


Maven has three main build phases:

Phase Description
clean Deletes old builds (mvn clean).
compile Compiles source code (mvn compile).
test Runs unit tests (mvn test).
package Packages the compiled code into a JAR/WAR file (mvn package).
install Installs the package in the local repository (mvn install).
deploy Deploys the project to a remote repository (mvn deploy).

8. Maven Plugins
Maven uses plugins to extend functionality.

Commonly Used Plugins

Plugin Purpose
maven-compiler-plugin Compiles Java source code.
maven-surefire-plugin Runs unit tests.
maven-jar-plugin Creates a JAR file.
maven-war-plugin Packages the project as a WAR (Web Archive).

Example: Configuring Java Version


<build>
<plugins>
<plugin>
<groupId>[Link]</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</build>

9. Running a Maven Project


To compile and run a Maven project:

mvn clean compile


mvn exec:java -[Link]="[Link]"

To package as a JAR:

mvn package
java -jar target/[Link]

10. Maven Profiles


Maven profiles allow configuring different environments (e.g., dev, test, prod).

Example: Defining Profiles in [Link]


<profiles>
<profile>
<id>dev</id>
<properties>
<env>Development</env>
</properties>
</profile>

<profile>
<id>prod</id>
<properties>
<env>Production</env>
</properties>
</profile>
</profiles>

To activate a profile:

mvn package -Pdev

11. Multi-Module Maven Projects


A multi-module project consists of a parent project and multiple sub-modules.

Example Structure
parent-project
│── [Link] (Parent POM)
│── module1
│ │── [Link]
│── module2
│ │── [Link]

Parent [Link]
<modules>
<module>module1</module>
<module>module2</module>
</modules>

To build all modules:

mvn clean install

12. Conclusion
Maven is a must-have tool for Java development, simplifying build management,
dependency resolution, and project structuring.

Feature Purpose
Dependency Management Automatically resolves libraries.
Build Automation Handles compilation, testing, and packaging.
Standardized Project Structure Ensures consistency across teams.
Integration with CI/CD Works with Jenkins, GitHub Actions, etc.

Would you like help with specific Maven configurations or plugin usage? 🚀

Maven Repositories – A Detailed Guide


1. Introduction to Maven Repositories
A Maven repository is a location where Maven stores and retrieves project dependencies,
plugins, and artifacts. Maven automatically downloads required dependencies from
repositories when building a project.

Types of Repositories in Maven

Maven uses three types of repositories:

Repository Type Description


Local Repository Cached on the developer's machine.
Central Repository Hosted by Maven ([Link]
Remote Repository Custom or third-party repositories like Nexus or Artifactory.

2. Local Repository
The local repository is stored on your machine and acts as a cache for dependencies
downloaded from remote repositories.

Location of Local Repository


By default, it is stored in:

C:\Users\YourUsername\.m2\repository (Windows)
~/.m2/repository (Mac/Linux)

You can find the local repository location by running:

mvn help:evaluate -Dexpression=[Link]

How It Works?

1. When you build a project, Maven checks if dependencies exist in the local
repository.
2. If not found, Maven downloads them from the central/remote repository and stores
them locally.

3. Central Repository
The Maven Central Repository is the default public repository used by Maven. It contains
thousands of open-source libraries.

URL of Maven Central Repository:

🔗 [Link]

Example: Fetching a Dependency from Central Repository

When you add the following dependency:

<dependency>
<groupId>[Link]</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>

Maven will:

1. Check the local repository.


2. If not found, download it from Maven Central.
3. Store it in .m2/repository for future use.

4. Remote Repository
A Remote Repository is a custom or third-party repository used when dependencies are not
available in the central repository.
Use Cases

 Private Libraries – Companies maintain their own repositories for internal


dependencies.
 Third-Party Libraries – Some vendors host their own repositories (e.g., JBoss,
Oracle).
 Faster Builds – Used in CI/CD pipelines with tools like Nexus or Artifactory.

Adding a Remote Repository in [Link]


<repositories>
<repository>
<id>jboss</id>

<url>[Link]
url>
</repository>
</repositories>

5. Deploying Artifacts to a Repository


Installing a JAR to Local Repository

If you have a custom JAR file ([Link]), install it locally:

mvn install:install-file -Dfile=[Link] -DgroupId=[Link] -


DartifactId=my-library -Dversion=1.0 -Dpackaging=jar

Deploying to a Remote Repository (e.g., Nexus, Artifactory)

1. Configure the distributionManagement section in [Link]:

<distributionManagement>
<repository>
<id>my-repo</id>
<url>[Link]
</repository>
</distributionManagement>

2. Deploy using:

mvn deploy

6. Snapshot vs. Release Repositories


Type Description
Release Repository Stores stable, production-ready versions.
Snapshot Repository Stores development versions (1.0-SNAPSHOT).
Maven uses the -SNAPSHOT suffix to mark non-final versions.

Example: Snapshot Dependency


<dependency>
<groupId>[Link]</groupId>
<artifactId>my-library</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

Maven will check for updated versions on every build.

7. Forcing Maven to Update Dependencies


If dependencies are outdated, force an update using:

mvn clean install -U

The -U flag tells Maven to update all snapshots from remote repositories.

8. Conclusion
Repository Type Purpose
Local Repository Stores cached dependencies on a developer’s machine.
Central Repository Default repository for open-source libraries.
Remote Repository Used for private or third-party dependencies.

Maven repositories ensure efficient dependency management, artifact sharing, and CI/CD
integration.

Would you like a hands-on example of deploying artifacts to Nexus or Artifactory? 🚀

Maven Dependencies and Plugins – A


Detailed Guide
1. Introduction to Maven Dependencies and Plugins
Maven simplifies dependency management and plugin execution to automate tasks like
compiling, testing, packaging, and deploying Java projects.

Why are Dependencies and Plugins Important?


✅ Dependencies – Automatically manage external libraries and JAR files.
✅ Plugins – Extend Maven functionality (e.g., compiling, testing, packaging).

2. Maven Dependencies
2.1 What are Maven Dependencies?
A dependency is an external library (JAR file) required by a Maven project. These
dependencies are declared in the [Link] file and are automatically downloaded from
repositories.

Example: Adding JUnit as a Dependency


<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>

🔹 groupId – Organization or project name (e.g., junit).


🔹 artifactId – Library name (junit).
🔹 version – Version of the library.
🔹 scope – Defines how Maven uses the dependency.

2.2 Dependency Scope


Maven uses different scopes to define when and how a dependency is included in the project.

Scope Description Example Use Case


Default scope, required at compile time and
compile Core libraries like Spring
runtime.
provided
Required at compile time but not included in the Servlet API (provided by
final JAR. Tomcat)
runtime Needed only at runtime, not at compile time. JDBC driver
test Used for testing only, not included in final build. JUnit, Mockito
system Uses a JAR from a local path. Rarely used
import
Used for BOM (Bill of Materials) in dependency Managing Spring
management. dependencies

Example: Different Scopes


<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.20</version>
<scope>compile</scope>
</dependency>

<dependency>
<groupId>[Link]</groupId>
<artifactId>[Link]-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>

2.3 Transitive Dependencies


Maven automatically resolves transitive dependencies (dependencies of dependencies).

Example: Spring Web Starter


<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.5.4</version>
</dependency>

This automatically includes:

 spring-core
 spring-web
 tomcat

🔹 Use mvn dependency:tree to see the full dependency hierarchy.

2.4 Excluding Transitive Dependencies


To remove unnecessary dependencies, use <exclusions>.

Example: Exclude logback from spring-boot-starter-web


<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.5.4</version>
<exclusions>
<exclusion>
<groupId>[Link]</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>
2.5 Dependency Management with BOM (Bill of
Materials)
A BOM helps manage dependency versions across multiple modules.

Example: Using Spring Boot BOM


<dependencyManagement>
<dependencies>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.5.4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

3. Maven Plugins
3.1 What are Maven Plugins?
Maven plugins are used to perform tasks like compilation, testing, packaging, and
deployment.

Types of Plugins

🔹 Build Plugins – Used during the build lifecycle (e.g., maven-compiler-plugin).


🔹 Reporting Plugins – Generate project reports (e.g., maven-site-plugin).

3.2 Commonly Used Maven Plugins


Plugin Purpose Example Usage
maven-compiler-plugin Compiles Java source code Compile Java 11 code
maven-surefire-plugin Runs unit tests Execute JUnit tests
maven-jar-plugin Creates a JAR file Package the application as JAR
maven-war-plugin Packages project as WAR Create a deployable web archive
maven-dependency-plugin Analyzes dependencies Show dependency tree
maven-shade-plugin Creates a fat JAR (Uber-JAR) Bundle dependencies inside JAR
maven-checkstyle-plugin Enforces coding standards Static code analysis
3.3 Configuring Plugins in [Link]
Example: maven-compiler-plugin (Set Java Version)
<build>
<plugins>
<plugin>
<groupId>[Link]</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</build>

Example: maven-jar-plugin (Create a JAR)


<build>
<plugins>
<plugin>
<groupId>[Link]</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<finalName>my-app</finalName>
</configuration>
</plugin>
</plugins>
</build>

To package the application:

mvn package

This creates:

target/[Link]

3.4 Executing Plugins from Command Line


You can run plugins directly using:

mvn plugin-name:goal

Example Commands
mvn compile # Compile source code
mvn clean # Delete target folder
mvn package # Create JAR/WAR
mvn test # Run tests
mvn dependency:tree # Show dependency hierarchy
mvn help:describe -Dplugin=compiler # Show plugin details

4. Conclusion
Feature Purpose
Dependencies Manages required libraries automatically.
Dependency Scope Defines when dependencies are needed.
Transitive Dependencies Automatically resolves dependency tree.
Plugins Automates tasks like compiling, packaging, testing.
Plugin Goals Run specific tasks (compile, test, package).

Maven dependencies and plugins streamline project management, making Java development
more efficient.

Would you like real-world examples or help with specific plugins? 🚀

Maven Goals and Build Lifecycle – A


Detailed Guide
1. Introduction to Maven Build Lifecycle and Goals
Maven follows a structured build process that consists of phases and goals. These help
automate tasks like compiling, testing, packaging, and deploying Java applications.

Key Terms:

 Build Lifecycle – A sequence of phases that define the steps of a build.


 Phases – Each phase represents a stage in the build process.
 Goals – Specific tasks executed within a phase (e.g., compiling code, running tests).

2. Maven Build Lifecycle


Maven has three built-in lifecycles:

Lifecycle Purpose
Clean Cleans the project (removes old builds).
Default The main lifecycle for building the project (compiling, testing, packaging).
Site Generates project documentation.

3. Default Lifecycle Phases


The default lifecycle consists of the following phases, executed in order:

Phase Description
validate Ensures all necessary information is available.
compile Compiles the source code.
test Runs unit tests.
package Packages compiled code into a JAR/WAR.
verify Verifies the package meets quality standards.
install Installs the package in the local repository.
deploy Deploys the package to a remote repository.

Example: Running the Build Lifecycle

Executing:

mvn package

Runs all previous phases:

1. validate
2. compile
3. test
4. package

4. Clean Lifecycle
The clean lifecycle removes old build artifacts before a new build.

Phase Description
pre-clean Runs tasks before cleaning.
clean Deletes the target/ directory.
post-clean Runs tasks after cleaning.

Example:
mvn clean

Removes:

/target

5. Site Lifecycle
The site lifecycle generates project documentation.
Phase Description
pre-site Runs before generating documentation.
site Generates project reports and documentation.
post-site Runs after generating documentation.
site-deploy Deploys documentation to a web server.

Example:
mvn site

Generates reports in:

target/site/[Link]

6. Maven Goals
A goal is a task executed within a phase.

Example: Goals in the Default Lifecycle

Phase Goal Example


compile maven-compiler-plugin:compile
test maven-surefire-plugin:test
package maven-jar-plugin:jar
install maven-install-plugin:install

Executing Specific Goals

You can run a goal manually:

mvn compiler:compile

This runs only the compile goal, skipping other phases.

7. Common Maven Commands


Command Description
mvn clean Deletes previous builds.
mvn compile Compiles Java source code.
mvn test Runs unit tests.
mvn package Creates a JAR/WAR file.
mvn install Installs the package to the local repository.
mvn deploy Deploys the package to a remote repository.
mvn site Generates project documentation.
8. Customizing the Build Lifecycle
Custom Goal Example: Running a Shell Script Before Build

Add this to [Link]:

<build>
<plugins>
<plugin>
<groupId>[Link]</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>echo</executable>
<arguments>
<argument>"Running validation
step..."</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

This prints a message during the validate phase.

9. Conclusion
Concept Purpose
Lifecycle Defines a sequence of build phases.
Phases Steps executed in order during the build.
Goals Specific tasks inside a phase.
Plugins Extend Maven’s functionality.

Maven’s build lifecycle and goals ensure a standardized and automated build process.

Would you like an example of a custom lifecycle plugin? 🚀

Project Object Model (POM) – Detailed


Guide
1. Introduction to [Link]
The Project Object Model (POM) is the core configuration file of a Maven project. It
contains project details, dependencies, plugins, build configurations, and more.

📌 POM File Location:


Every Maven project has a [Link] file located in the root directory.

📌 POM Structure:
A [Link] file is written in XML format and follows a hierarchical structure.

2. Basic Structure of [Link]


A minimal [Link] file:

<project xmlns="[Link]
xmlns:xsi="[Link]
xsi:schemaLocation="[Link]
[Link]
<modelVersion>4.0.0</modelVersion>

<groupId>[Link]</groupId>
<artifactId>my-app</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>

<name>My Maven Project</name>


<description>A simple Maven project</description>
</project>

Key Elements in [Link]

Tag Description Example


<modelVersion>
Maven POM version <modelVersion>4.0.0</modelVersion>
(always 4.0.0)
<groupId>
Unique identifier for the <groupId>[Link]</groupId>
project
<artifactId>
Project name <artifactId>my-app</artifactId>
(JAR/WAR name)
<version> Project version <version>1.0.0</version>

<packaging>
Defines the package <packaging>jar</packaging>
type (jar, war, pom)
<name> Project name <name>My Maven Project</name>

<description>
Short description of the <description>A simple Maven
project project</description>

3. Important Sections in [Link]


3.1 Dependencies Section

Used to add external libraries to the project.

📌 Example: Adding JUnit Dependency

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>

 📌 Dependencies are automatically downloaded from Maven repositories.


 📌 Use mvn dependency:tree to check dependency hierarchy.

3.2 Build Section

Used to define plugins, custom builds, and configurations.

📌 Example: Setting Java Version Using Compiler Plugin

<build>
<plugins>
<plugin>
<groupId>[Link]</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</build>

🔹 This ensures the project compiles with Java 11.

3.3 Repositories Section

Used to define where Maven should download dependencies from.

📌 Example: Using JCenter Repository

<repositories>
<repository>
<id>jcenter</id>
<url>[Link]
</repository>
</repositories>

📌 By default, Maven uses Maven Central Repository.

3.4 Properties Section

Used to define custom variables for version control.

📌 Example: Setting Property for Java Version

<properties>
<[Link]>11</[Link]>
<[Link]>11</[Link]>
</properties>

🔹 Now, instead of hardcoding Java versions in multiple places, just update the
properties section!

3.5 Profiles Section

Used to define different configurations for different environments (e.g., development,


production).

📌 Example: Defining a Development Profile

<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<env>development</env>
</properties>
</profile>
</profiles>

🔹 To activate a profile:

mvn clean install -Pdev

3.6 Dependency Management Section

Used to define versions for dependencies in multi-module projects.

📌 Example: Managing Dependency Versions


<dependencyManagement>
<dependencies>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.5.4</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>

3.7 Modules Section (For Multi-Module Projects)

Used to manage multiple projects inside one parent POM.

📌 Example: Defining Modules

<modules>
<module>module-a</module>
<module>module-b</module>
</modules>

📌 This means the parent POM will build both modules together.

4. Executing Maven Commands


Basic Commands

Command Description
mvn compile Compiles Java code.
mvn clean Deletes old builds.
mvn package Creates JAR/WAR file.
mvn install Installs project into local repository.
mvn deploy Deploys the artifact to a remote repository.
mvn site Generates project documentation.

Example: Compiling a Project


mvn compile

5. Understanding [Link] Hierarchy


Maven uses a parent-child structure:

1. Super POM (Default POM provided by Maven)


2. Parent POM (Custom base configuration)
3. Module POM (Specific project-level settings)

Example: Inheriting from Parent POM

📌 Parent POM (in root directory)

<project>
<groupId>[Link]</groupId>
<artifactId>parent-project</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
</project>

📌 Child POM (in submodule directory)

<project>
<parent>
<groupId>[Link]</groupId>
<artifactId>parent-project</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>submodule</artifactId>
</project>

🔹 The child POM inherits dependencies and settings from the parent POM.

6. Conclusion
Feature Purpose
Dependencies Automatically download required JARs.
Build Customize plugins and build configurations.
Profiles Define multiple configurations (dev, prod).
Repositories Define sources for dependencies.
Modules Manage multi-module projects.

📌 Maven's [Link] simplifies dependency management, build automation, and project


configuration. 🚀

Would you like help with customizing your POM file for a specific project? 😊

Let's build a Core Java Application using Maven! This will be a simple console-based
Java program that calculates the factorial of a number.

Project Structure
FactorialApp/
│── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/example/factorial/
│ │ │ └── [Link]
│ ├── test/
│ │ ├── java/
│ │ │ └── com/example/factorial/
│ │ │ └── [Link]
│── [Link]

Step 1: Create the Maven Project


Run the following command to generate a Maven project:

mvn archetype:generate -DgroupId=[Link] -


DartifactId=FactorialApp -DarchetypeArtifactId=maven-archetype-quickstart -
DinteractiveMode=false

This creates the basic project structure.

Step 2: Update [Link]


Edit the [Link] file to include the required dependencies and plugins.

📌 [Link]

<project xmlns="[Link]
xmlns:xsi="[Link]
xsi:schemaLocation="[Link]
[Link]
<modelVersion>4.0.0</modelVersion>

<groupId>[Link]</groupId>
<artifactId>FactorialApp</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>Factorial Calculator</name>
<description>Simple factorial calculator using Java</description>

<properties>
<[Link]>11</[Link]>
<[Link]>11</[Link]>
</properties>

<dependencies>
<!-- JUnit for testing -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Compiler Plugin -->
<plugin>
<groupId>[Link]</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>

<!-- Assembly Plugin to generate executable JAR -->


<plugin>
<groupId>[Link]</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.4.0</version>
<executions>
<execution>
<id>make-jar</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>

<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

Step 3: Write the Java Code


Create the main Java class that calculates the factorial of a number.

📌 [Link]

package [Link];

import [Link];

public class FactorialApp {


public static void main(String[] args) {
Scanner scanner = new Scanner([Link]);
[Link]("Enter a number: ");
int number = [Link]();
[Link]();

long result = factorial(number);


[Link]("Factorial of " + number + " is: " + result);
}

public static long factorial(int n) {


if (n < 0) {
throw new IllegalArgumentException("Number must be non-
negative.");
}
long fact = 1;
for (int i = 2; i <= n; i++) {
fact *= i;
}
return fact;
}
}

Step 4: Write Unit Tests


Create a test class to validate the factorial logic.

📌 [Link]

package [Link];

import static [Link];


import [Link];

public class FactorialAppTest {


@Test
public void testFactorial() {
assertEquals(1, [Link](0));
assertEquals(1, [Link](1));
assertEquals(2, [Link](2));
assertEquals(6, [Link](3));
assertEquals(24, [Link](4));
assertEquals(120, [Link](5));
}

@Test(expected = [Link])
public void testFactorialNegativeNumber() {
[Link](-5);
}
}

Step 5: Compile and Build the Project


To compile the Java code:

mvn compile

To run unit tests:

mvn test
To package the application into a JAR file:

mvn package

This creates the JAR file in the target/ directory.

Step 6: Run the Application


Run the generated JAR file:

java -jar target/[Link]

Example output:

Enter a number: 5
Factorial of 5 is: 120

Step 7: Deploy (Optional)


You can install the JAR into your local Maven repository:

mvn install

Or deploy it to a remote repository using:

mvn deploy

Summary
Step Description
1 Create a Maven project using mvn archetype:generate.
2 Define [Link] with dependencies and plugins.
3 Write the [Link] program.
4 Write test cases in [Link].
5 Compile and package using mvn package.
6 Run the application using java -jar.
7 Deploy using mvn install or mvn deploy.

🚀 Congratulations! You have built a Core Java application using Maven. 🚀

Would you like to extend the project with logging, a GUI, or database integration? 😃

You might also like