✅ Java Tutorial Example: Simple Calculator
// Java Program: Simple Calculator
import java.util.Scanner;
public class SimpleCalculator {
// Method to perform addition
public static int add(int a, int b) {
return a + b;
}
// Method to perform subtraction
public static int subtract(int a, int b) {
return a - b;
}
// Method to perform multiplication
public static int multiply(int a, int b) {
return a * b;
}
// Method to perform division
public static double divide(int a, int b) {
if (b != 0)
return (double) a / b;
else
return Double.NaN; // Not a Number
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Simple Calculator in Java");
System.out.print("Enter first number: ");
int num1 = input.nextInt();
System.out.print("Enter second number: ");
int num2 = input.nextInt();
System.out.println("Choose operation: + - * /");
char op = input.next().charAt(0);
double result = 0;
switch (op) {
case '+':
result = add(num1, num2);
break;
case '-':
result = subtract(num1, num2);
break;
case '*':
result = multiply(num1, num2);
break;
case '/':
result = divide(num1, num2);
break;
default:
System.out.println("Invalid operator!");
return;
}
System.out.println("Result: " + result);
}
}
✅ Sample Output:
Simple Calculator in Java
Enter first number: 10
Enter second number: 2
Choose operation: + - * /
*
Result: 20
✅ Java Basic Program: Print Name and Sum of Two Numbers
// Java Program to Print Name and Add Two Numbers
public class BasicExample {
public static void main(String[] args) {
// Printing a message
System.out.println("Hello, Java Learner!");
// Declare and initialize variables
int num1 = 10;
int num2 = 20;
// Add the numbers
int sum = num1 + num2;
// Print the result
System.out.println("The sum of " + num1 + " and " + num2 + " is: " + sum);
}
}
✅ Output:
Hello, Java Learner!
The sum of 10 and 20 is: 30
✅ Java Program: Constructor Example
// Java Program to Demonstrate Constructors
public class Student {
// Instance variables
String name;
int age;
// Constructor (same name as class, no return type)
public Student(String studentName, int studentAge) {
name = studentName;
age = studentAge;
}
// Method to display student info
public void displayInfo() {
System.out.println("Name: " + name);
System.out.println("Age: " + age);
}
// Main method
public static void main(String[] args) {
// Creating an object of Student and calling constructor
Student s1 = new Student("Aqdas", 21);
// Display student info
s1.displayInfo();
}
}
---
🔍 Explanation:
Constructor Name = Class Name
No return type (not even void)
It is automatically called when you create an object.
Used to initialize object values.
---
✅ Output:
Name: Aqdas
Age: 21
---
💡 Types of Constructors in Java:
1. Default Constructor – No parameters.
2. Parameterized Constructor – Takes arguments (like above).
3. Copy Constructor – Copies values from another object (manual in Java).
✅ Java Program: Static Method Example
// Java Program to Demonstrate Static Method
public class MathOperations {
// Static method to add two numbers
public static int add(int a, int b) {
return a + b;
}
// Main method
public static void main(String[] args) {
// Call the static method directly using class name
int result = MathOperations.add(10, 20);
System.out.println("Sum = " + result);
}
}
---
🔍 Explanation:
static keyword means the method belongs to the class, not the object.
You can call a static method without creating an object.
Syntax: ClassName.methodName() if calling from another class, or just methodName() if inside
the same class.
---
✅ Output:
Sum = 30
---
🧠 Quick Facts:
main() is also a static method.
Static methods cannot access non-static (instance) variables directly.
✅ Java Program: Non-Static Method Example
// Java Program to Demonstrate Non-Static Method
public class Greeting {
// Non-static method
public void sayHello() {
System.out.println("Hello, welcome to Java programming!");
}
public static void main(String[] args) {
// Create an object of the class
Greeting g1 = new Greeting();
// Call the non-static method using the object
g1.sayHello();
}
}
---
🔍 Explanation:
sayHello() is a non-static method (no static keyword).
You must create an object to call it.
Syntax: objectName.methodName()
---
✅ Output:
Hello, welcome to Java programming!
---
🧠 Quick Facts:
Non-static methods can access both static and non-static members of the class.
They are used when each object should have its own behavior or data.
✅ Java Program: Decision Making Example
// Java Program to Demonstrate Decision Making
import java.util.Scanner;
public class DecisionExample {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// Take user input
System.out.print("Enter your marks (0-100): ");
int marks = input.nextInt();
// Decision making using if-else-if
if (marks >= 90) {
System.out.println("Grade: A+");
} else if (marks >= 75) {
System.out.println("Grade: A");
} else if (marks >= 60) {
System.out.println("Grade: B");
} else if (marks >= 50) {
System.out.println("Grade: C");
} else if (marks >= 35) {
System.out.println("Grade: D");
} else {
System.out.println("Grade: Fail");
}
}
}
---
🔍 Explanation:
if, else if, and else are used for decision making.
Java checks conditions top-down, and executes the first true condition.
---
✅ Sample Output:
Enter your marks (0-100): 78
Grade: A
---
🧠 Quick Summary of Decision-Making Statements in Java:
Statement Use Case
if -Executes a block if condition is true
if-else -One block for true, one for false
if-else-if- Multiple conditions checked in order
switch Use for multiple constant choices
✅ Java Program: Loops Example
// Java Program to Demonstrate Loops
public class LoopExample {
public static void main(String[] args) {
// For Loop: Print 1 to 5
System.out.println("Using for loop:");
for (int i = 1; i <= 5; i++) {
System.out.println("i = " + i);
}
// While Loop: Print 1 to 5
System.out.println("\nUsing while loop:");
int j = 1;
while (j <= 5) {
System.out.println("j = " + j);
j++;
}
// Do-While Loop: Print 1 to 5
System.out.println("\nUsing do-while loop:");
int k = 1;
do {
System.out.println("k = " + k);
k++;
} while (k <= 5);
}
}
---
🔍 Explanation of Each Loop:
1. for loop – Best when the number of repetitions is known.
2. while loop – Used when the condition is checked before each iteration.
3. do-while loop – Always runs at least once, even if the condition is false.
---
✅ Output:
Using for loop:
i=1
i=2
i=3
i=4
i=5
Using while loop:
j=1
j=2
j=3
j=4
j=5
Using do-while loop:
k=1
k=2
k=3
k=4
k=5
✅ Java Program: Jump Statements Example
// Java Program to Demonstrate Jump Statements
public class JumpExample {
public static void main(String[] args) {
// Example of break
System.out.println("Using break:");
for (int i = 1; i <= 10; i++) {
if (i == 5) {
break; // Exit the loop when i is 5
}
System.out.println("i = " + i);
}
// Example of continue
System.out.println("\nUsing continue:");
for (int j = 1; j <= 5; j++) {
if (j == 3) {
continue; // Skip iteration when j is 3
}
System.out.println("j = " + j);
}
// Example of return
System.out.println("\nUsing return:");
showMessage();
}
// Method with return
public static void showMessage() {
System.out.println("This message is printed.");
return; // Ends the method early
// Any code below return won't execute
// System.out.println("This won't print.");
}
}
---
🔍 Explanation:
Jump Statement Purpose
break Exits the loop or switch block
continue Skips the current iteration of a loop
return Exits from a method
---
✅ Output:
Using break:
i=1
i=2
i=3
i=4
Using continue:
j=1
j=2
j=4
j=5
Using return:
This message is printed.
✅ Java Program: Abstraction Example
// Abstract class
abstract class Animal {
// Abstract method (no body)
abstract void sound();
// Non-abstract method
void sleep() {
System.out.println("Sleeping...");
}
}
// Subclass (inherits from Animal)
class Dog extends Animal {
// Provide implementation of abstract method
void sound() {
System.out.println("Dog barks");
}
}
public class AbstractionExample {
public static void main(String[] args) {
// Create object of Dog
Dog d = new Dog();
// Call abstract method (implemented)
d.sound();
// Call non-abstract method
d.sleep();
}
}
---
🔍 Explanation:
abstract class: Cannot be instantiated directly.
abstract void sound();: Method with no body, must be overridden.
Dog extends Animal: Subclass implements the abstract method.
You can call both abstract and concrete methods using the subclass object.
---
✅ Output:
Dog barks
Sleeping…
✅ Java Program: Encapsulation Example
// Class with Encapsulation
public class Person {
// Private data members (hidden from outside)
private String name;
private int age;
// Public setter method for name
public void setName(String newName) {
name = newName;
}
// Public getter method for name
public String getName() {
return name;
}
// Public setter method for age
public void setAge(int newAge) {
if (newAge > 0) {
age = newAge;
}
}
// Public getter method for age
public int getAge() {
return age;
}
// Main method to test encapsulation
public static void main(String[] args) {
Person p1 = new Person();
// Setting values using setter methods
p1.setName("Aqdas");
p1.setAge(21);
// Getting values using getter methods
System.out.println("Name: " + p1.getName());
System.out.println("Age: " + p1.getAge());
}
}
---
🔍 Explanation:
Private fields name and age are not directly accessible outside the class.
Getter and Setter methods allow controlled access.
This is Encapsulation — binding data and code together and restricting direct access.
---
✅ Output:
Name: Aqdas
Age: 21
---
🧠 Benefits of Encapsulation:
Protects data (security)
Easy to maintain and modify code
Achieves data hiding
Improves code flexibility and reusability
✅ Java Program: Inheritance Example
// Parent class (Base or Superclass)
class Animal {
void eat() {
System.out.println("This animal eats food.");
}
}
// Child class (Derived or Subclass)
class Dog extends Animal {
void bark() {
System.out.println("The dog barks.");
}
}
public class InheritanceExample {
public static void main(String[] args) {
// Create an object of Dog
Dog myDog = new Dog();
// Call method from parent class
myDog.eat();
// Call method from child class
myDog.bark();
}
}
---
🔍 Explanation:
class Dog extends Animal: Dog inherits from Animal.
Dog can use both its own methods and those from Animal.
This shows code reusability and hierarchical relationship.
---
✅ Output:
This animal eats food.
The dog barks.
---
🧠 Types of Inheritance in Java:
1. Single Inheritance (shown above)
2. Multilevel Inheritance
3. Hierarchical Inheritance
✅ Java Program: Polymorphism Example (Method Overriding)
// Parent class
class Animal {
void sound() {
System.out.println("Animal makes a sound");
}
}
// Child class 1
class Dog extends Animal {
void sound() {
System.out.println("Dog barks");
}
}
// Child class 2
class Cat extends Animal {
void sound() {
System.out.println("Cat meows");
}
}
public class PolymorphismExample {
public static void main(String[] args) {
// Parent class reference holding child objects (runtime polymorphism)
Animal a;
a = new Dog();
a.sound(); // Output: Dog barks
a = new Cat();
a.sound(); // Output: Cat meows
}
}
---
🔍 Explanation:
Method Overriding is used to achieve runtime polymorphism.
The method sound() behaves differently depending on the object (Dog or Cat).
The same method name acts in multiple forms.
---
✅ Output:
Dog barks
Cat meows
---
🧠 Types of Polymorphism in Java:
Type_(How it's Achieved)-Example
Compile-time_(Method Overloading)-Same method name, different parameters
Runtime_(Method Overriding)-Same method in child class
✅ Java Program: Inheritance + Method Overloading
// Parent class
class Calculator {
// Overloaded methods with different parameters
int add(int a, int b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
}
// Child class inheriting Calculator
class AdvancedCalculator extends Calculator {
// Additional method in child class
double add(double a, double b) {
return a + b;
}
}
public class OverloadingWithInheritance {
public static void main(String[] args) {
// Create object of child class
AdvancedCalculator calc = new AdvancedCalculator();
// Call overloaded methods from parent class
System.out.println("add(int, int): " + calc.add(10, 20));
System.out.println("add(int, int, int): " + calc.add(5, 10, 15));
// Call overloaded method from child class
System.out.println("add(double, double): " + calc.add(5.5, 4.5));
}
}
---
🔍 Explanation:
Method Overloading: Same method name add, but different parameter types/counts.
Overloading can happen within the same class or through inheritance.
AdvancedCalculator inherits overloaded methods from Calculator and adds another overloaded
version.
---
✅ Output:
add(int, int): 30
add(int, int, int): 30
add(double, double): 10.0
✅ Java Program: Exception Handling Example
// Java Program to Demonstrate try, catch, finally
public class ExceptionExample {
public static void main(String[] args) {
try {
// Code that may throw an exception
int a = 10;
int b = 0;
int result = a / b; // This will throw ArithmeticException
System.out.println("Result: " + result);
} catch (ArithmeticException e) {
// Code to handle exception
System.out.println("Exception caught: Division by zero is not allowed.");
} finally {
// This block always runs
System.out.println("Finally block: This will always execute.");
}
System.out.println("Program continues after exception handling.");
}
}
---
🔍 Explanation:
try: Code that may throw an exception.
catch: Handles the exception (e.g., ArithmeticException).
finally: Always executes — used for cleanup like closing files or connections.
---
✅ Output:
Exception caught: Division by zero is not allowed.
Finally block: This will always execute.
Program continues after exception handling.
---
🧠 Tip:
You can use multiple catch blocks for different exceptions.
finally will run whether or not an exception is thrown.
✅ 1. throw in Java
Used to manually throw an exception object.
🔸 Example: Using throw
public class ThrowExample {
public static void main(String[] args) {
int age = 15;
if (age < 18) {
// manually throwing exception
throw new ArithmeticException("Access denied - You must be 18 or older.");
} else {
System.out.println("Access granted - You are old enough!");
}
}
}
🧠 Output:
Exception in thread "main" java.lang.ArithmeticException: Access denied - You must be 18 or
older.
---
✅ 2. throws in Java
Used to declare exceptions that a method might throw. It tells the caller to handle it.
🔸 Example: Using throws
import java.io.*;
public class ThrowsExample {
// Method declares that it might throw IOException
public static void readFile() throws IOException {
FileReader file = new FileReader("nonexistent.txt");
BufferedReader fileInput = new BufferedReader(file);
// Read first line
System.out.println(fileInput.readLine());
fileInput.close();
}
public static void main(String[] args) {
try {
readFile(); // Must handle the exception
} catch (IOException e) {
System.out.println("File not found. Handled IOException.");
}
}
}
🧠 Output:
File not found. Handled IOException.
✅ What is a Checked Exception?
Checked exceptions are checked at compile-time.
The compiler forces you to handle them using try-catch or declare with throws.
Common examples: IOException, SQLException, FileNotFoundException
---
✅ Java Program: Checked Exception Example (FileNotFoundException)
import java.io.*; // For FileReader and FileNotFoundException
public class CheckedExceptionExample {
public static void main(String[] args) {
try {
// Attempt to open a file that doesn't exist
FileReader file = new FileReader("myfile.txt");
BufferedReader reader = new BufferedReader(file);
// Read first line
System.out.println(reader.readLine());
reader.close();
} catch (FileNotFoundException e) {
System.out.println("File not found! Please check the file name.");
} catch (IOException e) {
System.out.println("An I/O error occurred.");
}
}
}
---
✅ Output (if file doesn’t exist):
File not found! Please check the file name.
---
🔍 Explanation:
FileReader may throw FileNotFoundException (a checked exception).
readLine() may throw IOException.
Both are handled using try-catch blocks.
---
🧠 Key Points:
Feature Checked Exception
Checked at Compile-time
Must be handled? Yes (either try-catch or throws)
Examples IOException, SQLException, FileNotFoundException
Common Sources File operations, DB access
✅ Java Code: Unchecked Exception Example
public class UncheckedExceptionExample {
public static void main(String[] args) {
int num1 = 10;
int num2 = 0;
// This will throw an ArithmeticException (division by zero)
int result = num1 / num2;
System.out.println("Result: " + result);
}
}
---
🔍 Output:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at UncheckedExceptionExample.main(UncheckedExceptionExample.java:7)
---
📘 Explanation:
ArithmeticException is an example of an unchecked exception.
Unchecked exceptions in Java are subclasses of RuntimeException.
They are not required to be declared in the method signature or handled using try-catch.
The program compiles successfully but crashes at runtime.
---
✅ Handled Version (Optional - Using try-catch):
public class UncheckedExceptionHandled {
public static void main(String[] args) {
try {
int num1 = 10;
int num2 = 0;
int result = num1 / num2;
System.out.println("Result: " + result);
} catch (ArithmeticException e) {
System.out.println("Caught an exception: " + e.getMessage());
}
}
}
✅ Java Program: Byte Stream Example
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class ByteStreamExample {
public static void main(String[] args) {
try {
// Write data to a file using FileOutputStream (Byte Output Stream)
FileOutputStream fos = new FileOutputStream("example.txt");
String message = "Hello, Byte Stream!";
byte[] data = message.getBytes(); // Convert string to bytes
fos.write(data);
fos.close();
System.out.println("Data written to file successfully.");
// Read data from the file using FileInputStream (Byte Input Stream)
FileInputStream fis = new FileInputStream("example.txt");
int i;
System.out.println("Reading from file:");
while ((i = fis.read()) != -1) {
System.out.print((char) i); // Convert byte to char
}
fis.close();
} catch (IOException e) {
System.out.println("Error occurred: " + e.getMessage());
}
}
}
---
🔍 Explanation:
Class Purpose
FileOutputStream Writes bytes to a file
FileInputStream Reads bytes from a file
getBytes() Converts String to byte array
read() Reads one byte at a time
---
✅ Output:
Data written to file successfully.
Reading from file:
Hello, Byte Stream!
---
🧠 Key Points:
Byte streams are used for binary data (images, videos, audio, etc.).
For character data, use Character Streams (FileReader, FileWriter).
✅ Java Program: Character Stream Example
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CharacterStreamExample {
public static void main(String[] args) {
try {
// Writing to a file using FileWriter (Character Output Stream)
FileWriter writer = new FileWriter("char_example.txt");
writer.write("Hello, Character Stream in Java!");
writer.close();
System.out.println("Data written to file successfully.");
// Reading from the file using FileReader (Character Input Stream)
FileReader reader = new FileReader("char_example.txt");
int ch;
System.out.println("Reading from file:");
while ((ch = reader.read()) != -1) {
System.out.print((char) ch); // Convert int to char
}
reader.close();
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
---
🔍 Explanation:
Class Description
FileWriter Writes characters to a file
FileReader Reads characters from a file
write() Writes a string or character
read() Reads one character at a time (as int)
---
✅ Sample Output:
Data written to file successfully.
Reading from file:
Hello, Character Stream in Java!
---
🧠 When to Use Character Streams?
Use Character Streams for text files (like .txt, .csv)
Use Byte Streams for binary files (like .jpg, .mp3, .mp4)
✅ Java Program: Creating Thread by Extending Thread Class
// Creating a thread by extending Thread class
class MyThread extends Thread {
// Override the run() method
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println("Thread running: " + i);
try {
Thread.sleep(500); // Pause for 0.5 seconds
} catch (InterruptedException e) {
System.out.println("Thread interrupted.");
}
}
}
}
public class ThreadExample {
public static void main(String[] args) {
// Create object of the thread class
MyThread t1 = new MyThread();
// Start the thread
t1.start();
// Main thread work
for (int i = 1; i <= 5; i++) {
System.out.println("Main thread: " + i);
try {
Thread.sleep(500); // Pause for 0.5 seconds
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
}
}
}
---
🔍 Explanation:
Part Description
class MyThread extends Thread Custom thread class created by extending Thread
run() method Contains the code to be executed in the new thread
start() methodStarts the thread and calls run() internally
sleep()Pauses thread execution temporarily (in milliseconds)
---
✅ Sample Output (May Vary Due to Thread Scheduling):
Thread running: 1
Main thread: 1
Thread running: 2
Main thread: 2
...
---
🧠 Key Points:
Use start() (not run()) to begin a thread.
You can create multiple threads by creating multiple objects of the thread class.
Thread execution order is not guaranteed — depends on the scheduler.
✅ Java Program: Creating Thread by Implementing Runnable Interface
// Implementing Runnable interface
class MyRunnable implements Runnable {
// Override the run() method
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println("Child thread: " + i);
try {
Thread.sleep(500); // Pause for 0.5 seconds
} catch (InterruptedException e) {
System.out.println("Child thread interrupted.");
}
}
}
}
public class RunnableExample {
public static void main(String[] args) {
// Create object of MyRunnable
MyRunnable r1 = new MyRunnable();
// Wrap it in a Thread object and start
Thread t1 = new Thread(r1);
t1.start();
// Main thread task
for (int i = 1; i <= 5; i++) {
System.out.println("Main thread: " + i);
try {
Thread.sleep(500); // Pause for 0.5 seconds
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
}
}
}
---
🔍 Explanation:
Component Description
implements RunnableCreates a class that can run as a thread
run() method Code to execute in the new thread
Thread t = new Thread(r1) Thread created with Runnable object
t.start()Starts the thread execution
---
✅ Sample Output (Varies due to thread scheduling):
Main thread: 1
Child thread: 1
Main thread: 2
Child thread: 2
...
---
🧠 Why Prefer Runnable over Thread?
Java allows single inheritance — if your class extends Thread, it can’t extend anything else.
With Runnable, your class stays more flexible.
✅ Java Program: Using Thread.sleep() Method
public class SleepExample {
public static void main(String[] args) {
System.out.println("Program starts...");
for (int i = 1; i <= 5; i++) {
System.out.println("Count: " + i);
try {
// Pause execution for 1 second (1000 milliseconds)
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Thread interrupted.");
}
}
System.out.println("Program ends.");
}
}
---
🔍 Explanation:
Method Description
Thread.sleep(ms) Pauses the current thread for given milliseconds
try-catch Required to handle InterruptedException
---
✅ Output:
Program starts...
Count: 1
Count: 2
Count: 3
Count: 4
Count: 5
Program ends.
(Each count appears after 1 second delay)
---
🧠 Key Points:
sleep() is a static method of the Thread class.
Throws InterruptedException, so must be in a try-catch block.
Often used in multithreading, animations, or polling loops.
✅Java program for suspend(),resume() and stop()
The methods suspend(), resume(), and stop() were part of early Java thread control, but they
are now deprecated because they are unsafe and can cause deadlocks or inconsistent object
states.
⚠️ Deprecated Warning
suspend() can freeze a thread forever if not properly resumed.
stop() can terminate a thread instantly without cleaning up resources.
resume() works only after suspend(), but again, it's unsafe.
---
✅ Recommended Alternative Approach
We now use flags (booleans) to pause, resume, or stop a thread safely.
---
✅ Java Program: Custom Suspend, Resume, Stop Using Flags
class MyThread extends Thread {
private boolean suspended = false;
private boolean stopped = false;
public void run() {
for (int i = 1; i <= 10; i++) {
if (stopped) {
break; // exit loop if stopped
}
// skip printing if suspended
if (!suspended) {
System.out.println("Running: " + i);
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println("Thread interrupted.");
}
// wait here if suspended
synchronized (this) {
while (suspended) {
try {
wait();
} catch (InterruptedException e) {
System.out.println("Thread interrupted during wait.");
}
}
}
}
System.out.println("Thread finished.");
}
// Custom suspend method
synchronized void customSuspend() {
suspended = true;
}
// Custom resume method
synchronized void customResume() {
suspended = false;
notify();
}
// Custom stop method
void customStop() {
stopped = true;
customResume(); // ensure thread exits wait
}
}
public class ThreadControlExample {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
try {
Thread.sleep(2000);
t.customSuspend();
System.out.println("Thread suspended...");
Thread.sleep(2000);
t.customResume();
System.out.println("Thread resumed...");
Thread.sleep(2000);
t.customStop();
System.out.println("Thread stopped...");
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
}
}
---
✅ Sample Output:
Running: 1
Running: 2
Running: 3
Running: 4
Thread suspended...
Thread resumed...
Running: 5
Running: 6
...
Thread stopped...
Thread finished.
---
🧠 Summary:
Method Deprecated? Safe Alternative
✅
✅
suspend() YesUse a boolean flag & wait()
✅
resume() YesUse a flag with notify()
stop() YesUse a flag to break loop
✅ Java Program: Using Thread.yield()
class MyThread extends Thread {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(getName() + " - iteration " + i);
// Suggest current thread to pause and let others run
Thread.yield();
try {
Thread.sleep(300);
} catch (InterruptedException e) {
System.out.println(getName() + " interrupted.");
}
}
}
}
public class YieldExample {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.setName("Thread-1");
t2.setName("Thread-2");
t1.start();
t2.start();
}
}
---
🔍 Explanation:
Method Description
Thread.yield() Suggests that the current thread pause to let others run
setName() Sets a thread name for easier tracking in output
sleep()Adds a small delay to see interleaving behavior
---
✅ Sample Output (May Vary):
Thread-1 - iteration 1
Thread-2 - iteration 1
Thread-1 - iteration 2
Thread-2 - iteration 2
...
yield() does not guarantee the thread will pause — it’s only a suggestion to the scheduler.
---
🧠 Key Points:
yield() is a static method.
Used to improve thread cooperation.
Mainly useful when multiple threads have equal priority.
Behavior is platform-dependent and not guaranteed.
✅ Java Program: Using isAlive() and join()
class MyThread extends Thread {
public void run() {
System.out.println(getName() + " is starting...");
try {
Thread.sleep(2000); // Simulate some work (2 seconds)
} catch (InterruptedException e) {
System.out.println(getName() + " was interrupted.");
}
System.out.println(getName() + " has finished.");
}
}
public class ThreadJoinIsAliveExample {
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.setName("Thread-1");
// Start the thread
t1.start();
// Check if thread is alive
System.out.println("Is Thread-1 alive? " + t1.isAlive());
try {
// Main thread waits until t1 finishes
t1.join();
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
// After join, thread is definitely finished
System.out.println("Is Thread-1 alive after join? " + t1.isAlive());
System.out.println("Main thread ends.");
}
}
---
🔍 Explanation:
Method Description
isAlive() Returns true if the thread has started and not yet finished
join() Makes the current thread wait until the called thread completes
---
✅ Sample Output:
Is Thread-1 alive? true
Thread-1 is starting...
Thread-1 has finished.
Is Thread-1 alive after join? false
Main thread ends.
---
🧠 Key Notes:
isAlive() is helpful to check thread status.
join() is used to pause main thread until another thread completes its work.
join() ensures sequential execution when needed.
✅ Java Program: Interrupting a Thread
class MyThread extends Thread {
public void run() {
try {
for (int i = 1; i <= 5; i++) {
System.out.println("Thread running: " + i);
Thread.sleep(1000); // Sleep for 1 second
}
} catch (InterruptedException e) {
System.out.println("Thread was interrupted during sleep.");
}
System.out.println("Thread exiting normally.");
}
}
public class InterruptExample {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
try {
Thread.sleep(3000); // Let the thread run for 3 seconds
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
// Interrupt the thread
t.interrupt();
System.out.println("Main thread requested interruption.");
}
}
---
✅ Output (May Vary):
Thread running: 1
Thread running: 2
Thread running: 3
Thread was interrupted during sleep.
Thread exiting normally.
Main thread requested interruption.
---
🔍 Explanation:
Method Description
interrupt() Requests the thread to stop or break out of sleep/wait
InterruptedException Thrown if thread is interrupted during sleep or wait
isInterrupted()Checks thread’s interrupt status (optional, not shown above)
---
🧠 Key Points:
Threads don’t stop instantly; they need cooperation to check for interrupts.
Use try-catch with InterruptedException for safe interruption.
You can also use Thread.currentThread().isInterrupted() inside a loop if needed.
✅ Java Program: Thread Priority and Sleep Example
class MyThread extends Thread {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(getName() + " [Priority: " + getPriority() + "] - Count: " + i);
try {
Thread.sleep(500); // Sleep for 0.5 second
} catch (InterruptedException e) {
System.out.println(getName() + " was interrupted.");
}
}
}
}
public class ThreadPriorityExample {
public static void main(String[] args) {
// Create 3 threads
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
// Name the threads
t1.setName("LowPriorityThread");
t2.setName("NormalPriorityThread");
t3.setName("HighPriorityThread");
// Set priorities
t1.setPriority(Thread.MIN_PRIORITY); // Priority 1
t2.setPriority(Thread.NORM_PRIORITY); // Priority 5
t3.setPriority(Thread.MAX_PRIORITY); // Priority 10
// Start the threads
t1.start();
t2.start();
t3.start();
}
}
---
🔍 Explanation:
Feature Usage
setPriority() Sets thread priority (1 to 10)
sleep(ms) Pauses thread for given milliseconds
getPriority() Returns the priority of the thread
getName() Returns the name of the thread
---
✅ Sample Output (May Vary Due to Scheduler):
HighPriorityThread [Priority: 10] - Count: 1
NormalPriorityThread [Priority: 5] - Count: 1
LowPriorityThread [Priority: 1] - Count: 1
HighPriorityThread [Priority: 10] - Count: 2
...
> 📝 Output order is not guaranteed — the thread scheduler decides based on priority but not
strictly.
---
🧠 Key Points:
Thread priority ranges from:
Thread.MIN_PRIORITY (1)
Thread.NORM_PRIORITY (5)
Thread.MAX_PRIORITY (10)
Thread priority is a hint, not a command.
sleep() allows visible switching between threads.
✅ Java Program: Synchronized Method Example
class Table {
// Synchronized method
synchronized void printTable(int n) {
for (int i = 1; i <= 5; i++) {
System.out.println(n + " x " + i + " = " + (n * i));
try {
Thread.sleep(400); // delay for visibility
} catch (InterruptedException e) {
System.out.println("Thread interrupted.");
}
}
}
}
// Thread class calling the synchronized method
class MyThread1 extends Thread {
Table t;
MyThread1(Table t) {
this.t = t;
}
public void run() {
t.printTable(5);
}
}
class MyThread2 extends Thread {
Table t;
MyThread2(Table t) {
this.t = t;
}
public void run() {
t.printTable(100);
}
}
public class SynchronizedMethodExample {
public static void main(String[] args) {
Table obj = new Table(); // shared object
MyThread1 t1 = new MyThread1(obj);
MyThread2 t2 = new MyThread2(obj);
t1.start();
t2.start();
}
}
---
🔍 Explanation:
Component Role
synchronized Ensures only one thread at a time can enter the method
Shared Object (obj) Both threads use the same object, so synchronization works
Thread.sleep()Simulates delay to observe interleaving
---
✅ Sample Output (Without Mixing):
5x1=5
5 x 2 = 10
5 x 3 = 15
5 x 4 = 20
5 x 5 = 25
100 x 1 = 100
100 x 2 = 200
100 x 3 = 300
100 x 4 = 400
100 x 5 = 500
✅ Synchronised block program -
A synchronized block is used to lock only a specific part of code, unlike a synchronized method
which locks the entire method.
---
✅ Java Program: Synchronized Block Example
class Printer {
void printNumbers(int n) {
// Synchronized block to lock only the print section
synchronized (this) {
for (int i = 1; i <= 5; i++) {
System.out.println(n + " x " + i + " = " + (n * i));
try {
Thread.sleep(400); // Simulate delay
} catch (InterruptedException e) {
System.out.println("Thread interrupted.");
}
}
}
}
}
// Thread classes
class MyThread1 extends Thread {
Printer p;
MyThread1(Printer p) {
this.p = p;
}
public void run() {
p.printNumbers(5);
}
}
class MyThread2 extends Thread {
Printer p;
MyThread2(Printer p) {
this.p = p;
}
public void run() {
p.printNumbers(100);
}
}
public class SynchronizedBlockExample {
public static void main(String[] args) {
Printer p = new Printer(); // shared object
MyThread1 t1 = new MyThread1(p);
MyThread2 t2 = new MyThread2(p);
t1.start();
t2.start();
}
}
---
✅ Sample Output (No Mixing):
5x1=5
5 x 2 = 10
...
5 x 5 = 25
100 x 1 = 100
100 x 2 = 200
...
(Order may vary, but blocks won't interleave due to synchronization.)
---
🧠 Why Use Synchronized Block?
Feature Description
synchronized (this) Locks only the block, not the whole method
Efficient Better performance than locking an entire method
Safer Sharing Prevents data corruption in multi-threading scenarios
✅Inter_thread communication -
Inter-Thread Communication in Java using wait(), notify(), and synchronized.
This is commonly used when one thread needs to wait for a signal from another thread before
continuing.
---
✅ Java Program: Inter-Thread Communication Example
class SharedResource {
boolean flag = false;
synchronized void produce() {
if (flag) {
try {
wait(); // Wait until flag is false
} catch (InterruptedException e) {
System.out.println("Producer interrupted.");
}
}
System.out.println("Producing...");
flag = true;
notify(); // Notify waiting thread
}
synchronized void consume() {
if (!flag) {
try {
wait(); // Wait until flag is true
} catch (InterruptedException e) {
System.out.println("Consumer interrupted.");
}
}
System.out.println("Consuming...");
flag = false;
notify(); // Notify waiting thread
}
}
// Producer thread
class Producer extends Thread {
SharedResource resource;
Producer(SharedResource resource) {
this.resource = resource;
}
public void run() {
for (int i = 1; i <= 5; i++) {
resource.produce();
}
}
}
// Consumer thread
class Consumer extends Thread {
SharedResource resource;
Consumer(SharedResource resource) {
this.resource = resource;
}
public void run() {
for (int i = 1; i <= 5; i++) {
resource.consume();
}
}
}
public class InterThreadCommunicationExample {
public static void main(String[] args) {
SharedResource resource = new SharedResource();
Producer p = new Producer(resource);
Consumer c = new Consumer(resource);
p.start();
c.start();
}
}
---
✅ Sample Output:
Producing...
Consuming...
Producing...
Consuming...
Producing...
Consuming...
Producing...
Consuming...
Producing...
Consuming...
---
🔍 Explanation:
Method Description
wait() Pauses the current thread and releases the lock
notify()Wakes up a single waiting thread (if any)
synchronized Ensures thread-safe access to shared methods or blocks
---
🧠 Key Points:
Only used inside synchronized context.
Both wait() and notify() must be called on the same object monitor.
Helps avoid busy-waiting loops.
✅ Java Program: Factorial Using Interface
// Step 1: Define the interface
interface FactorialCalculator {
int factorial(int n);
}
// Step 2: Implement the interface in a class
class MyFactorial implements FactorialCalculator {
public int factorial(int n) {
int fact = 1;
for (int i = 1; i <= n; i++) {
fact *= i;
}
return fact;
}
}
// Step 3: Use the implementation in main method
public class FactorialInterfaceExample {
public static void main(String[] args) {
FactorialCalculator fc = new MyFactorial();
int number = 5;
int result = fc.factorial(number);
System.out.println("Factorial of " + number + " is: " + result);
}
}
---
✅ Output:
Factorial of 5 is: 120
---
🔍 Explanation:
Part Role
interface Declares the method factorial(int n)
implements MyFactorial class provides the logic for factorial
main() Creates an object and calls the method via the interface
---
🧠 Why Use Interface Here?
Good for demonstrating abstraction.
Useful if you want multiple implementations of factorial (e.g., recursive, iterative).
Encourages loose coupling and better design.
✅ Java Program: Lambda Expression Example
// Step 1: Define a functional interface
@FunctionalInterface
interface Operation {
int compute(int a, int b);
}
public class LambdaExample {
public static void main(String[] args) {
// Step 2: Use lambda expression to define method behavior
// Addition
Operation add = (a, b) -> a + b;
System.out.println("Addition: " + add.compute(10, 5));
// Subtraction
Operation sub = (a, b) -> a - b;
System.out.println("Subtraction: " + sub.compute(10, 5));
// Multiplication
Operation mul = (a, b) -> a * b;
System.out.println("Multiplication: " + mul.compute(10, 5));
// Division
Operation div = (a, b) -> a / b;
System.out.println("Division: " + div.compute(10, 5));
}
}
---
✅ Output:
Addition: 15
Subtraction: 5
Multiplication: 50
Division: 2
---
🔍 Explanation:
Part Description
@FunctionalInterfaceEnsures interface has only one abstract method
(a, b) -> a + b Lambda expression replacing a full method
Operation interface Functional interface used for lambda
---
🧠 Why Use Lambda?
Reduces boilerplate code
Commonly used with streams, event handling, and collections
Enables functional programming style in Java
---
✅ Part 1: Method Reference Example
Syntax: ClassName::methodName
It replaces a lambda expression that calls an existing method.
🔸 Example: Static Method Reference
@FunctionalInterface
interface MessagePrinter {
void print();
}
class Message {
static void show() {
System.out.println("Hello from a static method!");
}
}
public class MethodReferenceExample {
public static void main(String[] args) {
// Method reference to a static method
MessagePrinter printer = Message::show;
printer.print(); // Calls Message.show()
}
}
---
✅ Part 2: Constructor Reference Example
Syntax: ClassName::new
It replaces a lambda that creates a new object.
🔸 Example: Constructor Reference
@FunctionalInterface
interface PersonFactory {
Person create(String name, int age);
}
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("Person created: " + name + ", Age: " + age);
}
}
public class ConstructorReferenceExample {
public static void main(String[] args) {
// Constructor reference
PersonFactory factory = Person::new;
// Create a new Person object
Person p1 = factory.create("John", 30);
}
}
✅ Java Program: Stream API Example
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamAPIExample {
public static void main(String[] args) {
// List of integers
List<Integer> numbers = Arrays.asList(10, 15, 20, 25, 30, 35);
✅
// Filter even numbers and collect into a new list
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
System.out.println("Even Numbers: " + evenNumbers);
✅
// Square each number and print
System.out.println("Squares:");
numbers.stream()
.map(n -> n * n)
.forEach(System.out::println);
✅
// Sum of all numbers
int sum = numbers.stream()
.mapToInt(Integer::intValue)
.sum();
System.out.println("Sum of all numbers: " + sum);
}
}
---
✅ Sample Output:
Even Numbers: [10, 20, 30]
Squares:
100
225
400
625
900
1225
Sum of all numbers: 135
---
🔍 Explanation:
Method Purpose
.stream() Converts collection to stream
.filter() Filters data based on a condition
.map() Transforms each element
.forEach() Performs action for each item
.collect() Gathers results into a collection
.sum() Calculates total
---
🧠 Stream API Benefits:
Works on collections (List, Set)
Supports pipeline-style processing
Reduces boilerplate using lambda expressions
✅ Java Program: Using forEach() Method
import java.util.Arrays;
import java.util.List;
public class ForEachExample {
public static void main(String[] args) {
// Create a list of numbers
List<Integer> numbers = Arrays.asList(5, 10, 15, 20, 25);
✅
// Using forEach with lambda expression
System.out.println("Using lambda expression:");
numbers.forEach(n -> System.out.println("Number: " + n));
✅
// Using forEach with method reference
System.out.println("\nUsing method reference:");
numbers.forEach(System.out::println);
}
}
---
✅ Sample Output:
Using lambda expression:
Number: 5
Number: 10
Number: 15
Number: 20
Number: 25
Using method reference:
5
10
15
20
25
---
🔍 Explanation:
Method Purpose
forEach() Iterates over each element in the
collection
n -> ... Lambda expression
System.out::println Method reference for printing
---
🧠 Key Points:
forEach() is available in Iterable and Stream API.
Clean, functional-style iteration.
Often used in combination with stream().
✅ Java Program: Default Method in Interface
// Step 1: Define interface with a default method
interface MyInterface {
void show(); // Abstract method
// Default method with implementation
default void greet() {
System.out.println("Hello from default method!");
}
}
// Step 2: Implement the interface
class MyClass implements MyInterface {
public void show() {
System.out.println("Implementation of show() method.");
}
}
// Step 3: Use in main()
public class DefaultMethodExample {
public static void main(String[] args) {
MyClass obj = new MyClass();
obj.show(); // Calls implemented method
obj.greet(); // Calls default method from interface
}
}
---
✅ Output:
Implementation of show() method.
Hello from default method!
---
🔍 Explanation:
Feature Description
default method Provides a method body inside
an interface
Purpose Allows interface evolution
without breaking old code
Overridable Can be overridden in
implementing class (optional)
---
🧠 Why Use Default Methods?
Add new features to interfaces without affecting existing classes.
Useful in interface inheritance, collections, functional interfaces, etc.
✅ Java Program: Reference to a Non-Static Method
// Functional interface with one abstract method
@FunctionalInterface
interface MessagePrinter {
void printMessage();
}
// Class with a non-static (instance) method
class MyPrinter {
public void display() {
System.out.println("Hello from a non-static method!");
}
}
public class NonStaticMethodReferenceExample {
public static void main(String[] args) {
// Create an object of the class
MyPrinter printer = new MyPrinter();
// Reference to non-static method using object
MessagePrinter ref = printer::display;
// Call the method via interface reference
ref.printMessage();
}
}
---
✅ Output:
Hello from a non-static method!
---
🔍 Explanation:
Element Description
printer::display Reference to a non-static
method via object
MessagePrinter Functional interface with single
method
ref.printMessage() Calls the referenced method
(display())
---
🧠 Key Points:
You need an object to refer to a non-static method.
The method reference object::methodName works only when method signatures match the
functional interface method.
Helps make code cleaner and more readable, often used with lambda expressions and streams.
✅ Java Program: Base64 Encoding and Decoding
import java.util.Base64;
public class Base64Example {
public static void main(String[] args) {
String originalString = "HelloJava123";
✅
// Encode
String encodedString = Base64.getEncoder().encodeToString(originalString.getBytes());
System.out.println("Encoded String: " + encodedString);
✅
// Decode
byte[] decodedBytes = Base64.getDecoder().decode(encodedString);
String decodedString = new String(decodedBytes);
System.out.println("Decoded String: " + decodedString);
}
}
---
✅ Output:
Encoded String: SGVsbG9KYXZhMTIz
Decoded String: HelloJava123
---
🔍 Explanation:
Part Purpose
Base64.getEncoder()Returns a Base64 encoder object
.encodeToString(byte[]) Encodes a byte array to a Base64 string
Base64.getDecoder()Returns a Base64 decoder object
.decode(String) Decodes a Base64 string to byte array
---
🧠 Base64 is commonly used for:
Encoding binary data to text (e.g., images, files)
Secure data transfer in URLs, headers, tokens, etc.
✅ Java Program: Base64 Decoding Example
import java.util.Base64;
public class Base64DecodingExample {
public static void main(String[] args) {
// Base64 encoded string (e.g., "HelloWorld" → "SGVsbG9Xb3JsZA==")
String encodedString = "SGVsbG9Xb3JsZA==";
✅
// Decode the string
byte[] decodedBytes = Base64.getDecoder().decode(encodedString);
String decodedString = new String(decodedBytes);
✅
// Output
System.out.println("Encoded String: " + encodedString);
System.out.println("Decoded String: " + decodedString);
}
}
---
✅ Output:
Encoded String: SGVsbG9Xb3JsZA==
Decoded String: HelloWorld
---
🔍 Explanation:
Method Description
Base64.getDecoder()Returns a Base64 decoder
.decode(String) Decodes the Base64 string to
byte[]
new String(decodedBytes) Converts the byte array
to readable text
---
🧠 Use Cases:
Decoding data received from web APIs
Extracting original data from encoded tokens
Reading encoded files or credentials
✅ Java Program: Try-With-Resources Example
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class TryWithResourcesExample {
public static void main(String[] args) {
// Try-with-resources block
try (BufferedReader br = new BufferedReader(new FileReader("sample.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println("Line: " + line);
}
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
---
✅ What You Need:
Create a file named sample.txt in the project directory.
Put some sample text in it like:
Hello Java
Try with resources is awesome!
---
✅ Output (if file contains 2 lines):
Line: Hello Java
Line: Try with resources is awesome!
---
🔍 Explanation:
Element Description
try (BufferedReader br...) Automatically closes the BufferedReader after use
No finally block No need to manually close the resource (like br.close())
AutoCloseable The resource must implement AutoCloseable interface
---
🧠 Benefits of Try-With-Resources:
No memory leaks
No need for finally block
Cleaner code
More readable and safe
✅ Java Program: Using Built-in and Custom Annotations
🔸 Part 1: Using Built-in Annotation (@Override)
class Animal {
void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override // This tells the compiler we are overriding a method
void sound() {
System.out.println("Dog barks");
}
}
public class BuiltInAnnotationExample {
public static void main(String[] args) {
Dog d = new Dog();
d.sound();
}
}
---
✅ Output:
Dog barks
---
🔸 Part 2: Creating and Using a Custom Annotation
import java.lang.annotation.*;
// Step 1: Create a custom annotation
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface MyAnnotation {
String value() default "Default message";
}
// Step 2: Apply annotation
class Demo {
@MyAnnotation(value = "Hello from annotation!")
public void show() {
System.out.println("Inside show() method.");
}
}
// Step 3: Access annotation via reflection
public class CustomAnnotationExample {
public static void main(String[] args) throws Exception {
Demo d = new Demo();
d.show();
// Accessing annotation using reflection
MyAnnotation annotation = d.getClass()
.getMethod("show")
.getAnnotation(MyAnnotation.class);
System.out.println("Annotation value: " + annotation.value());
}
}
---
✅ Output:
Inside show() method.
Annotation value: Hello from annotation!
—
✅ 1. Non-Static (Regular) Inner Class Example
class Outer {
int outerVar = 100;
// Inner class
class Inner {
void display() {
System.out.println("Inside Inner class. outerVar = " + outerVar);
}
}
}
public class InnerClassExample {
public static void main(String[] args) {
// Create outer class object
Outer outer = new Outer();
// Create inner class object using outer class object
Outer.Inner inner = outer.new Inner();
// Call inner class method
inner.display();
}
}
---
✅ Output:
Inside Inner class. outerVar = 100
---
✅ 2. Static Inner Class Example
class OuterStatic {
static int data = 50;
static class StaticInner {
void msg() {
System.out.println("Inside Static Inner class. Data = " + data);
}
}
}
public class StaticInnerClassExample {
public static void main(String[] args) {
// Create static inner class object directly using outer class
OuterStatic.StaticInner obj = new OuterStatic.StaticInner();
obj.msg();
}
}
---
✅ Output:
Inside Static Inner class. Data = 50
---
🧠 Summary of Inner Class Types:
Type Can access outer instance members? Needs outer object?
✅ ✅
❌ ❌
Non-static inner Yes Yes
✅ ✅
Static inner No (only static members) No
✅ ✅
Local inner (inside method) (within method)
Anonymous inner (used for one-time use) Yes
✅ Anonymous class -
An anonymous class is a one-time use class without a name, typically used for:
Implementing interfaces
Extending a class
Handling events or threads
---
✅ Example 1: Anonymous Class Implementing an Interface
// Functional interface with one method
interface Greetable {
void greet();
}
public class AnonymousClassExample {
public static void main(String[] args) {
// Anonymous inner class implementing Greetable
Greetable obj = new Greetable() {
public void greet() {
System.out.println("Hello from anonymous class!");
}
};
obj.greet(); // Call method
}
}
---
✅ Output:
Hello from anonymous class!
---
✅ Example 2: Anonymous Class Extending a Class
class Animal {
void sound() {
System.out.println("Animal makes a sound");
}
}
public class AnonymousExtendsExample {
public static void main(String[] args) {
// Anonymous class extending Animal
Animal a = new Animal() {
@Override
void sound() {
System.out.println("Dog barks (overridden in anonymous class)");
}
};
a.sound(); // Calls overridden method
}
}
---
✅ Output:
Dog barks (overridden in anonymous class)
---
🧠 Key Features:
Feature Description
No class name Defined and used in one place
Used for one-time logic Often passed to threads, listeners, callbacks, etc.
Can implement/override Interfaces or superclass methods
✅ Anonymous object -
An anonymous object is an object that is created and used without assigning it to a reference
variable. It’s useful when you need an object only once (e.g., calling a single method).
---
✅ Java Program: Anonymous Object Example
class Message {
void show() {
System.out.println("Hello from an anonymous object!");
}
}
public class AnonymousObjectExample {
public static void main(String[] args) {
// Creating and using an anonymous object
new Message().show();
// You can’t reuse this object again, since it has no reference
}
}
---
✅ Output:
Hello from an anonymous object!
---
🧠 Why Use Anonymous Objects?
Use Case Explanation
One-time method calls Object needed only once (e.g., new A().method())
Saves memory and reduces clutter No need to store references
Often used in GUI or testing Where temporary use is sufficient
---
⚠️ Limitation:
You can't reuse the object — it has no name or reference.
✅ What is the Diamond Operator in Java?
The diamond operator (<>) is used with generics to let the compiler infer the type on the
right-hand side, so you don’t need to repeat it.
---
✅ Java Program: Diamond Operator Example
import java.util.ArrayList;
import java.util.List;
public class DiamondOperatorExample {
public static void main(String[] args) {
// Without Diamond Operator (Java 6 and earlier)
List<String> listOld = new ArrayList<String>();
listOld.add("Java 6");
System.out.println("Old style list: " + listOld);
// With Diamond Operator (Java 7+)
List<String> listNew = new ArrayList<>();
listNew.add("Java 7+");
System.out.println("New style list: " + listNew);
}
}
---
✅ Output:
Old style list: [Java 6]
New style list: [Java 7+]
---
🧠 Why Use the Diamond Operator?
BenefitDescription
Less Code No need to repeat the generic type
Readable & Cleaner Code looks simpler and easier to maintain
Type Safety Still ensures generic type safety at compile time
---
🔍 Where It’s Used:
With collections (ArrayList<>, HashMap<>, etc.)
With custom generic classes
✅ Java Program: Switch Expression Example
public class SwitchExpressionExample {
public static void main(String[] args) {
String day = "WEDNESDAY";
✅
// Switch Expression returns a value
int workingHours = switch (day) {
case "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY" -> 8;
case "SATURDAY" -> 4;
case "SUNDAY" -> 0;
default -> throw new IllegalArgumentException("Invalid day: " + day);
};
System.out.println("Working hours on " + day + ": " + workingHours);
}
}
---
✅ Output:
Working hours on WEDNESDAY: 8
---
🔍 Explanation:
Feature Description
-> syntax Cleaner, arrow-based case expressions
switch as an expression Returns a value and can be assigned to a variable
default -> Required if not all cases are handled explicitly
Multiple case labels Supported using commas, e.g., case "MONDAY", "TUESDAY"
---
🧠 Benefits Over Traditional Switch:
More concise and readable
Can return values directly
Prevents fall-through (no need for break)
Works well with enum, String, and primitive types
✅ What is yield in Java?
yield is used in switch expressions to return a value from a multi-line block.
It's only needed when the case contains a block ({}) instead of the short -> form.
---
✅ Java Program: Using yield in a Switch Expression
public class YieldKeywordExample {
public static void main(String[] args) {
String grade = "B";
String result = switch (grade) {
case "A" -> "Excellent";
case "B" -> {
System.out.println("Grade B selected");
yield "Very Good";
}
case "C" -> "Good";
default -> {
yield "Invalid grade";
}
};
System.out.println("Result: " + result);
}
}
---
✅ Output:
Grade B selected
Result: Very Good
---
🔍 Why Use yield?
Feature Purpose
yield Returns a value from a block in switch expression
Only needed When using block form {} inside a case
Replaces return return is not allowed inside a switch expression
✅ What is a Record in Java?
A record is a special type of class that:
Is immutable by default
Is used to store data only
Automatically generates:
constructor
getters
toString(), equals(), and hashCode() methods
---
✅ Java Program: Record Example
// Define a record
public record Person(String name, int age) {}
public class RecordExample {
public static void main(String[] args) {
// Create a record object
Person p1 = new Person("Aqdas", 22);
// Access record fields
System.out.println("Name: " + p1.name());
System.out.println("Age: " + p1.age());
// Print the whole object (uses auto-generated toString)
System.out.println("Person Info: " + p1);
}
}
---
✅ Output:
Name: Aqdas
Age: 22
Person Info: Person[name=Aqdas, age=22]
---
🧠 Key Features of Records:
Feature Description
Immutable Fields are final and cannot be changed
Concise Less boilerplate code than normal classes
Auto-generated Constructor, getters, toString(), etc.
Useful for DTOs Great for APIs, data transfer, etc.
---
🛑 Limitations:
Cannot extend other classes (they implicitly extend java.lang.Record)
Cannot define instance fields outside the constructor
All fields are final and must be initialized
✅ What is a Sealed Class/Interface?
A sealed class/interface restricts which classes can extend or implement it.
Ensures controlled inheritance.
Subclasses must be marked as **permitted** using:
final → cannot be extended further
sealed → continue restriction
non-sealed → removes restriction
---
✅ Java Program: Sealed Class and Interface Example
// ✅ Sealed interface with permitted implementors
sealed interface Shape permits Circle, Rectangle, Triangle {}
// ✅Final class - cannot be extended
final class Circle implements Shape {
public void draw() {
System.out.println("Drawing Circle");
}
}
// ✅
Sealed class - allows only permitted subclasses
sealed class Rectangle implements Shape permits Square, BigRectangle {
public void draw() {
System.out.println("Drawing Rectangle");
}
}
// ✅ Final subclass of Rectangle
final class Square extends Rectangle {
public void draw() {
System.out.println("Drawing Square");
}
}
// ✅Non-sealed subclass - open to be extended by anyone
non-sealed class BigRectangle extends Rectangle {
public void draw() {
System.out.println("Drawing BigRectangle");
}
}
// ✅ Final class - cannot be subclassed
final class Triangle implements Shape {
public void draw() {
System.out.println("Drawing Triangle");
}
}
public class SealedExample {
public static void main(String[] args) {
Shape s1 = new Circle();
Shape s2 = new Square();
Shape s3 = new BigRectangle();
Shape s4 = new Triangle();
((Circle)s1).draw();
((Square)s2).draw();
((BigRectangle)s3).draw();
((Triangle)s4).draw();
}
}
---
✅ Output:
Drawing Circle
Drawing Square
Drawing BigRectangle
Drawing Triangle
---
🔍 Key Concepts:
Keyword Meaning
sealed Only allowed classes can extend/implement
permits Declares the permitted subclasses
final Cannot be subclassed
non-sealed Open for extension (removes restriction)
---
🧠 Why Use Sealed Classes/Interfaces?
Improve code security and readability
Enable better compiler checks
Useful for domain modeling, enums with behavior, pattern matching, etc.
✅ What is Iterator in Java?
Iterator is used to traverse (iterate) elements of a collection (like ArrayList, HashSet, etc.).
Belongs to java.util package.
Common methods:
hasNext() → checks if the collection has more elements
next() → returns the next element
remove() → removes the last returned element (optional)
---
✅ Java Program: Iterator Example with ArrayList
import java.util.ArrayList;
import java.util.Iterator;
public class IteratorExample {
public static void main(String[] args) {
// Create a list of strings
ArrayList<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Mango");
fruits.add("Orange");
// Get the iterator
Iterator<String> it = fruits.iterator();
System.out.println("Fruits list using Iterator:");
// Traverse the list
while (it.hasNext()) {
String fruit = it.next();
System.out.println(fruit);
}
}
}
---
✅ Output:
Fruits list using Iterator:
Apple
Banana
Mango
Orange
---
🧠 Key Points:
Method Description
iterator() Returns an Iterator object
hasNext() Returns true if there are more elements
next() Returns the next element
remove() Removes current element (optional & rare use)
✅ Java Program: Basic ArrayList Operations
import java.util.ArrayList;
public class ArrayListExample {
public static void main(String[] args) {
// Create an ArrayList of Strings
ArrayList<String> names = new ArrayList<>();
//✅ Add elements
names.add("Aqdas");
names.add("John");
names.add("Sara");
names.add("Ravi");
//✅ Access elements by index
System.out.println("First name: " + names.get(0)); // Aqdas
//✅ Size of ArrayList
System.out.println("Total names: " + names.size());
//✅ Loop through elements
System.out.println("All names:");
for (String name : names) {
System.out.println(name);
}
//✅ Remove an element
names.remove("John");
//✅ Check if element exists
if (names.contains("Sara")) {
System.out.println("Sara is in the list.");
}
//✅ Final list
System.out.println("Final list: " + names);
}
}
---
✅ Output:
First name: Aqdas
Total names: 4
All names:
Aqdas
John
Sara
Ravi
Sara is in the list.
Final list: [Aqdas, Sara, Ravi]
---
🧠 Key Methods of ArrayList:
Method Description
add() Adds an element
get(index) Returns element at given index
remove() Removes by value or index
contains() Checks if element exists
size() Returns number of elements
clear() Removes all elements
✅Java program -basic linkedlist operation -
import java.util.LinkedList;
public class LinkedListExample {
public static void main(String[] args) {
LinkedList<String> cities = new LinkedList<>();
// Add elements
cities.add("Delhi");
cities.add("Mumbai");
cities.addFirst("Kolkata");
cities.addLast("Chennai");
// Access elements
System.out.println("First city: " + cities.getFirst());
System.out.println("Last city: " + cities.getLast());
// Remove element
cities.remove("Mumbai");
// Print all cities
System.out.println("Cities list: " + cities);
}
}
Output:
First city: Kolkata
Last city: Chennai
Cities list: [Kolkata, Delhi, Chennai]
✅using a Vector in Java-
A Vector is a legacy class in the Java Collection Framework (like ArrayList), but it's
synchronized (thread-safe).
---
✅ Java Program: Vector Example
import java.util.Vector;
public class VectorExample {
public static void main(String[] args) {
// Create a Vector of Strings
Vector<String> languages = new Vector<>();
// ✅
Add elements to the vector
languages.add("Java");
languages.add("Python");
languages.add("C++");
languages.add("JavaScript");
// ✅
Access elements by index
System.out.println("First language: " + languages.get(0));
// ✅ Size of vector
System.out.println("Total languages: " + languages.size());
//✅ Check if an element exists
if (languages.contains("Python")) {
System.out.println("Python is in the list.");
}
//✅ Remove an element
languages.remove("C++");
//✅ Display all elements using for-each
System.out.println("Languages:");
for (String lang : languages) {
System.out.println(lang);
}
}
}
---
✅ Output:
First language: Java
Total languages: 4
Python is in the list.
Languages:
Java
Python
JavaScript
---
🧠 Key Points about Vector:
Feature Description
Synchronized Thread-safe (unlike ArrayList)
Dynamic array Grows as needed
Slower Slightly slower than ArrayList
Legacy Mostly replaced by ArrayList
now
✅using a Stack in Java.-
A Stack follows the LIFO (Last-In, First-Out) principle and is part of Java's java.util package.
---
✅ Java Program: Stack Example
import java.util.Stack;
public class StackExample {
public static void main(String[] args) {
// Create a Stack of Strings
Stack<String> books = new Stack<>();
✅
// Push elements onto the stack
books.push("Java");
books.push("Python");
books.push("C++");
✅
// Peek at the top element
System.out.println("Top book: " + books.peek()); // C++
✅
// Pop the top element
String removed = books.pop();
System.out.println("Removed book: " + removed); // C++
✅
// Check if stack is empty
System.out.println("Is stack empty? " + books.isEmpty());
✅
// Print all elements
System.out.println("Books in stack: " + books);
}
}
---
✅ Output:
Top book: C++
Removed book: C++
Is stack empty? false
Books in stack: [Java, Python]
---
🧠 Key Methods of Stack:
Method Description
push() Adds item to the top
pop() Removes and returns the top item
peek() Returns the top item (no remove)
isEmpty() Checks if the stack is empty
search() Returns position of item from top
✅using a Queue in Java -
using the LinkedList implementation (since Queue is an interface).
---
✅ Java Program: Queue Example Using LinkedList
import java.util.LinkedList;
import java.util.Queue;
public class QueueExample {
public static void main(String[] args) {
// Create a Queue of Strings
Queue<String> customers = new LinkedList<>();
✅
// Add elements to the queue
customers.add("Alice");
customers.add("Bob");
customers.add("Charlie");
✅
// View the front of the queue
System.out.println("First customer: " + customers.peek()); // Alice
✅
// Remove elements (FIFO)
System.out.println("Serving: " + customers.poll()); // Alice
System.out.println("Serving: " + customers.poll()); // Bob
✅
// Remaining in queue
System.out.println("Remaining customers: " + customers);
}
}
---
✅ Output:
First customer: Alice
Serving: Alice
Serving: Bob
Remaining customers: [Charlie]
---
🧠 Key Methods of Queue:
Method Description
add(). Adds an element (throws error if full)
offer(). Adds an element (returns false if full)
peek() Returns head without removing (null if
empty)
poll() Removes and returns head (null if
empty)
remove() Like poll() but throws exception if
empty
✅ What is LinkedHashSet?
LinkedHashSet is a Set that:
Does not allow duplicates
Maintains insertion order
It is part of java.util package.
---
✅ Java Program: LinkedHashSet Example
import java.util.LinkedHashSet;
public class LinkedHashSetExample {
public static void main(String[] args) {
// Create a LinkedHashSet of Strings
LinkedHashSet<String> cities = new LinkedHashSet<>();
//✅ Add elements
cities.add("Delhi");
cities.add("Mumbai");
cities.add("Chennai");
cities.add("Delhi"); // Duplicate, will be ignored
//✅ Print elements (in insertion order)
System.out.println("Cities in LinkedHashSet:");
for (String city : cities) {
System.out.println(city);
}
//✅ Check for an element
if (cities.contains("Chennai")) {
System.out.println("Chennai is present.");
}
//✅ Remove an element
cities.remove("Mumbai");
//✅ Final set
System.out.println("Final set: " + cities);
}
}
---
✅ Output:
Cities in LinkedHashSet:
Delhi
Mumbai
Chennai
Chennai is present.
Final set: [Delhi, Chennai]
---
🧠 Key Features of LinkedHashSet:
Feature Description
No duplicates Automatically removes repeated elements
Maintains order Keeps the order in which elements were added
Performance Slower than HashSet, but ordered
✅ What is TreeSet in Java?
TreeSet is a class in java.util package that implements the Set interface.
It:
Stores unique elements
Sorts elements automatically in ascending order
Is based on a Red-Black Tree (self-balancing binary search tree)
---
✅ Java Program: TreeSet Example
import java.util.TreeSet;
public class TreeSetExample {
public static void main(String[] args) {
// Create a TreeSet of integers
TreeSet<Integer> numbers = new TreeSet<>();
// ✅ Add elements
numbers.add(30);
numbers.add(10);
numbers.add(50);
numbers.add(20);
numbers.add(10); // Duplicate, will be ignored
✅
// Print elements (automatically sorted)
System.out.println("Numbers in TreeSet:");
for (int num : numbers) {
System.out.println(num);
}
✅
// First and Last elements
System.out.println("Smallest: " + numbers.first());
System.out.println("Largest: " + numbers.last());
✅
// Remove an element
numbers.remove(20);
System.out.println("After removing 20: " + numbers);
}
}
---
✅ Output:
Numbers in TreeSet:
10
20
30
50
Smallest: 10
Largest: 50
After removing 20: [10, 30, 50]
---
🧠 Key Features of TreeSet:
Feature Description
No duplicates Automatically removes duplicate elements
Sorted. Elements are stored in ascending order
Null not allowed Does not allow null elements
Slower than HashSet Because it maintains sorted order
✅ What is HashMap in Java?
A HashMap is a part of the Java Collections Framework that stores data in key-value pairs.
It:
Allows unique keys
Allows one null key and multiple null values
Does not maintain insertion order
---
✅ Java Program: HashMap Example
import java.util.HashMap;
public class HashMapExample {
public static void main(String[] args) {
// Create a HashMap with Integer keys and String values
HashMap<Integer, String> students = new HashMap<>();
✅
// Add key-value pairs
students.put(101, "Aqdas");
students.put(102, "Ravi");
students.put(103, "Sara");
students.put(104, "John");
✅
// Access a value using key
System.out.println("Student with ID 102: " + students.get(102));
✅
// Loop through all key-value pairs
System.out.println("All students:");
for (Integer id : students.keySet()) {
System.out.println("ID: " + id + ", Name: " + students.get(id));
}
// ✅Remove an entry
students.remove(104);
// ✅Final map
System.out.println("Final student list: " + students);
}
}
---
✅ Output:
Student with ID 102: Ravi
All students:
ID: 101, Name: Aqdas
ID: 102, Name: Ravi
ID: 103, Name: Sara
ID: 104, Name: John
Final student list: {101=Aqdas, 102=Ravi, 103=Sara}
---
🧠 Key Methods of HashMap:
Method Description
put(key, value)Adds or replaces key-value pair
get(key) Retrieves value by key
remove(key) Removes entry by key
keySet() Returns all keys
values() Returns all values
entrySet() Returns key-value pairs as Map.Entry objects
✅ What is LinkedHashMap?
A LinkedHashMap:
Stores key-value pairs
Maintains the insertion order
Allows one null key and multiple null values
Is slightly slower than HashMap, but ordered
---
✅ Java Program: LinkedHashMap Example
import java.util.LinkedHashMap;
import java.util.Map;
public class LinkedHashMapExample {
public static void main(String[] args) {
// Create a LinkedHashMap with Integer keys and String values
LinkedHashMap<Integer, String> books = new LinkedHashMap<>();
//✅ Add key-value pairs
books.put(101, "Java");
books.put(102, "Python");
books.put(103, "C++");
books.put(104, "JavaScript");
//✅ Display all entries (in insertion order)
System.out.println("Books list:");
for (Map.Entry<Integer, String> entry : books.entrySet()) {
System.out.println("ID: " + entry.getKey() + ", Title: " + entry.getValue());
}
//✅ Remove an entry
books.remove(103);
//✅ Final map
System.out.println("After removal: " + books);
}
}
---
✅ Output:
Books list:
ID: 101, Title: Java
ID: 102, Title: Python
ID: 103, Title: C++
ID: 104, Title: JavaScript
After removal: {101=Java, 102=Python, 104=JavaScript}
---
✅ What is TreeMap in Java?
A TreeMap:
Stores key-value pairs in sorted (ascending) order by keys
Does not allow null keys
Belongs to java.util package
Implements the NavigableMap interface
---
✅ Java Program: TreeMap Example
import java.util.TreeMap;
import java.util.Map;
public class TreeMapExample {
public static void main(String[] args) {
// Create a TreeMap with Integer keys and String values
TreeMap<Integer, String> students = new TreeMap<>();
✅
// Add key-value pairs
students.put(105, "Aqdas");
students.put(101, "Ravi");
students.put(108, "Sara");
students.put(103, "John");
✅
// Display all entries (sorted by key)
System.out.println("Student list (sorted by ID):");
for (Map.Entry<Integer, String> entry : students.entrySet()) {
System.out.println("ID: " + entry.getKey() + ", Name: " + entry.getValue());
}
✅
// Get first and last key
System.out.println("Lowest ID: " + students.firstKey());
System.out.println("Highest ID: " + students.lastKey());
}
}
---
✅ Output:
Student list (sorted by ID):
ID: 101, Name: Ravi
ID: 103, Name: John
ID: 105, Name: Aqdas
ID: 108, Name: Sara
Lowest ID: 101
Highest ID: 108
---
🧠 Key Features of TreeMap:
Feature Description
Sorted. Automatically sorts by keys (ascending)
No null keys Throws NullPointerException if null key added
NavigableMap- Provides methods like firstKey(), lastKey()
✅ What is a Comparator?
A Comparator is used to define custom sorting logic.
It is part of java.util package.
You can sort by any field (e.g., name, age, etc.) in ascending or descending order.
---
✅ Java Program: Comparator Example
import java.util.*;
// ✅ Custom class
class Student {
int id;
String name;
// Constructor
Student(int id, String name) {
this.id = id;
this.name = name;
}
// To print student details
public String toString() {
return id + " - " + name;
}
}
// ✅Comparator to sort by name
class NameComparator implements Comparator<Student> {
public int compare(Student s1, Student s2) {
return s1.name.compareTo(s2.name); // ascending order
}
}
// ✅Comparator to sort by ID (descending)
class IdDescendingComparator implements Comparator<Student> {
public int compare(Student s1, Student s2) {
return s2.id - s1.id; // descending order
}
}
public class ComparatorExample {
public static void main(String[] args) {
List<Student> list = new ArrayList<>();
list.add(new Student(103, "Zara"));
list.add(new Student(101, "Aqdas"));
list.add(new Student(102, "John"));
System.out.println("Original List:");
for (Student s : list) {
System.out.println(s);
}
//✅ Sort by name
Collections.sort(list, new NameComparator());
System.out.println("\nSorted by Name:");
for (Student s : list) {
System.out.println(s);
}
//✅ Sort by ID descending
Collections.sort(list, new IdDescendingComparator());
System.out.println("\nSorted by ID (Descending):");
for (Student s : list) {
System.out.println(s);
}
}
}
---
✅ Output:
Original List:
103 - Zara
101 - Aqdas
102 - John
Sorted by Name:
101 - Aqdas
102 - John
103 - Zara
Sorted by ID (Descending):
103 - Zara
102 - John
101 - Aqdas
Feature Description
compare(a, b)Returns -1, 0, or 1 for sorting
✅ What is Comparable in Java?
It’s an interface in java.lang package.
Used to define the natural ordering of objects.
Must override the compareTo() method.
---
✅ Java Program: Comparable Example
import java.util.*;
// ✅ Student class implements Comparable
class Student implements Comparable<Student> {
int id;
String name;
Student(int id, String name) {
this.id = id;
this.name = name;
}
//✅ Define natural sorting by ID (ascending)
public int compareTo(Student s) {
return this.id - s.id;
}
//✅ To display object info
public String toString() {
return id + " - " + name;
}
}
public class ComparableExample {
public static void main(String[] args) {
List<Student> list = new ArrayList<>();
list.add(new Student(103, "Zara"));
list.add(new Student(101, "Aqdas"));
list.add(new Student(102, "John"));
✅
// Sort using Comparable
Collections.sort(list);
System.out.println("Sorted Students by ID (natural order):");
for (Student s : list) {
System.out.println(s);
}
}
}
---
✅ Output:
Sorted Students by ID (natural order):
101 - Aqdas
102 - John
103 - Zara
✅ What is the Properties Class?
Properties is a subclass of Hashtable.
Used to store key-value pairs where both key and value are Strings.
Commonly used to manage configuration data (like .properties files).
---
✅ Java Program: Properties Class Example
import java.util.Properties;
import java.util.Set;
public class PropertiesExample {
public static void main(String[] args) {
// Create a Properties object
Properties appProps = new Properties();
✅
// Set properties
appProps.setProperty("username", "admin");
appProps.setProperty("password", "12345");
appProps.setProperty("environment", "production");
✅
// Get a property
String user = appProps.getProperty("username");
System.out.println("Username: " + user);
✅
// Print all key-value pairs
System.out.println("\nAll Properties:");
Set<String> keys = appProps.stringPropertyNames();
for (String key : keys) {
System.out.println(key + " = " + appProps.getProperty(key));
}
}
}
---
✅ Output:
Username: admin
All Properties:
username = admin
password = 12345
environment = production
---
🧠 Key Methods of Properties:
Method Description
setProperty(k, v) Adds or updates a property
getProperty(k) Returns the value for key k
stringPropertyNames() Returns all keys as a Set
load() / store() Used for reading/writing .properties files