📚 Chapters

☕ Java Programming

Unit 1 — Introduction to Classes in Java

Chapter 1 — Java Fundamentals
☕ JAVA FUNDAMENTALS - MIND MAP
OOP Paradigms → Objects, Classes, Encapsulation, Inheritance, Polymorphism, Abstraction
Java Platform → JVM (bytecode executor), JDK (development), JRE (runtime), Reflection (runtime inspection)
Data Types → Primitive (8 types) & Reference (objects, arrays)
Operators → Arithmetic, Relational, Logical, Assignment, Unary
Control Flow → if-else, switch, for, while, do-while
Arrays → Fixed-size collections → Searching (Linear, Binary) & Sorting (Bubble, Selection)

1. Object-Oriented Programming Paradigms

📖 What is OOP?
A way to write programs using "objects" that hold data and actions. Code is organized around real-world things instead of just functions.

Why OOP? Before OOP, programs were written procedurally - code executed top-to-bottom sequentially. As programs grew larger, this became difficult to manage, debug, and maintain. OOP solves this by organizing code into logical units (objects) that mirror real-world entities.

💡 Real-life Example:
Think of a Car:
Object: Your specific red Toyota car parked outside
Attributes (Data): color="red", model="Toyota", speed=0, fuel=50L, engine="running"
Methods (Behavior): start(), stop(), accelerate(), brake(), refuel()
📌 Six Key OOP Concepts (Detailed Explanation):
1. Class:
A blueprint/template that defines what data and actions an object will have. No memory is used until an object is actually created from it.
// Class definition (blueprint) class Car { // Attributes/Properties String color; String model; int speed; // Behavior/Methods void start() { System.out.println("Car started"); } void accelerate() { speed += 10; System.out.println("Speed: " + speed); } }
2. Object:
An actual instance made from a class with real values in memory. Class = cookie cutter, Object = actual cookie. Many objects can be made from one class, each with different data.
// Creating objects (actual instances) Car myCar = new Car(); myCar.color = "Red"; myCar.model = "Toyota"; myCar.speed = 0; myCar.start(); // Output: Car started myCar.accelerate(); // Output: Speed: 10 Car yourCar = new Car(); yourCar.color = "Blue"; yourCar.model = "Honda"; // Different object, different values!
3. Encapsulation:
Wrapping data + methods in one class and hiding data using access modifiers (private/public). Outside code accesses data only through public methods — like a capsule hiding medicine inside.
💡 Real-life Analogy:
ATM machine - You can check balance and withdraw money (public methods), but you cannot directly access the vault or change your balance manually (private data).
class BankAccount { // Private data (hidden from outside) private double balance; private String accountNumber; // Public methods (controlled access) public void deposit(double amount) { if (amount > 0) { balance += amount; } } public double getBalance() { return balance; // Read-only access } } BankAccount acc = new BankAccount(); // acc.balance = 10000; // ERROR! Cannot access private acc.deposit(5000); // OK! Using public method
4. Inheritance:
Child class gets all properties and methods of a parent class and can add its own. Promotes reusability — write once, use many times. (IS-A rule: Dog IS-A Animal)
💡 Real-life Analogy:
You inherit features from your parents (eye color, height genes) but you're still a unique person with additional qualities.
// Parent class class Vehicle { String brand; int speed; void start() { System.out.println("Vehicle starting..."); } } // Child class inherits from Vehicle class Car extends Vehicle { int doors = 4; void drive() { System.out.println("Car driving..."); } } Car myCar = new Car(); myCar.brand = "Toyota"; // Inherited from Vehicle myCar.start(); // Inherited method myCar.drive(); // Own method
5. Polymorphism:
Same method name, different behavior depending on the object. Two types: overloading (same class, different params) and overriding (child redefines parent method).
💡 Real-life Analogy:
A person can be a student at college, son at home, employee at work - same person, different behaviors in different contexts.
class Animal { void sound() { System.out.println("Animal makes sound"); } } class Dog extends Animal { void sound() { System.out.println("Woof! Woof!"); } } class Cat extends Animal { void sound() { System.out.println("Meow! Meow!"); } } Animal a1 = new Dog(); Animal a2 = new Cat(); a1.sound(); // Output: Woof! Woof! a2.sound(); // Output: Meow! Meow! // Same method name, different behavior!
6. Abstraction:
Hide complex details, show only what the user needs. Focus on "what it does" not "how." Like using a car's accelerator — you don't need to know how the engine works.
💡 Real-life Analogy:
TV Remote - You press "Volume Up" button (simple interface) but don't know the complex electronic circuits inside that actually increase volume.
// Abstract class (cannot create object) abstract class Vehicle { // Abstract method (no implementation) abstract void start(); // Concrete method (has implementation) void stop() { System.out.println("Vehicle stopped"); } } class Car extends Vehicle { // Must provide implementation void start() { System.out.println("Car engine started"); } } // Vehicle v = new Vehicle(); // ERROR! Car c = new Car(); c.start(); // User doesn't see complex implementation

2. Features of Object-Oriented Programming

📖 Benefits of OOP: Makes code easier to write, debug, maintain, and scale compared to old procedural programming.
✓ Modularity: Code is divided into separate, independent modules (classes). Each class handles specific functionality. Easy to understand and maintain.

✓ Reusability: Write code once in a class, use it multiple times through objects and inheritance. Saves development time and effort.

✓ Maintainability: Changes in one class don't affect other classes (if properly encapsulated). Bug fixes and updates are easier.

✓ Security: Data hiding through encapsulation. Private variables cannot be accessed directly from outside. Controlled access through public methods.

✓ Scalability: Easy to add new features by creating new classes without modifying existing code. Supports large project growth.

✓ Code Organization: Logical structure that mirrors real-world entities. Easier for teams to collaborate.

✓ Flexibility: Polymorphism allows same interface for different data types. Makes code more flexible and extensible.

3. Java Virtual Machine, JDK, JRE & Reflection API

📖 "Write Once, Run Anywhere":
Java compiles to bytecode (not machine code). The JVM on any platform (Windows/Mac/Linux) runs this same bytecode — making Java platform-independent.
JDK — Java Development Kit:
The full package for developers. Contains everything needed to write, compile, and run Java programs.

Includes: JRE + Compiler (javac) + Debugger + Development tools
Use when: You are writing/developing Java code.
JRE — Java Runtime Environment:
The package needed to run Java programs. Does NOT include compiler.

Includes: JVM + Libraries (java.lang, java.util, etc.)
Use when: You only need to run a Java application (end user).
JVM — Java Virtual Machine:
The engine that actually executes bytecode line by line. It is platform-specific — Windows JVM, Mac JVM, Linux JVM — but they all understand the same bytecode.

Analogy: JVM = Translator that converts Java bytecode into OS-specific machine instructions.
ComponentFull FormContainsUsed By
JDKJava Development KitJRE + Compiler + ToolsDevelopers
JREJava Runtime EnvironmentJVM + LibrariesEnd users
JVMJava Virtual MachineBytecode executorBoth
💡 Memory Trick — Nested: JDK ⊃ JRE ⊃ JVM
JDK is the biggest (contains everything), JVM is the core engine inside.
💡 Java Compilation Flow:
Source (.java) → javac → Bytecode (.class) → JVM → Machine Code → Output
Java Reflection API:
📖 Reflection: A Java API (java.lang.reflect) that lets a program inspect and manipulate classes, methods, fields, and constructors at runtime — even ones it doesn't know about at compile time.
import java.lang.reflect.*; class Student { private String name = "Ankush"; public void greet() { System.out.println("Hello!"); } } public class ReflectionDemo { public static void main(String[] args) throws Exception { Class cls = Student.class; System.out.println("Class name: " + cls.getName()); // list all declared methods for (Method m : cls.getDeclaredMethods()) { System.out.println("Method: " + m.getName()); } // list all declared fields for (Field f : cls.getDeclaredFields()) { System.out.println("Field: " + f.getName()); } } } // Output: Class name: Student Method: greet Field: name
💡 Used in: Frameworks (Spring, Hibernate), IDEs (auto-complete), unit testing (JUnit), and serialization libraries — they inspect classes without knowing them in advance.

4. Data Types in Java

📖 Data Type: Specifies the type and size of data that a variable can store. Java is a statically typed language — you must declare the type before using a variable.

A. Primitive Data Types (8 types):

TypeSizeDefaultRange / Example
byte1 byte0-128 to 127
short2 bytes0-32,768 to 32,767
int4 bytes0-2B to 2B (most common)
long8 bytes0LVery large numbers, use L suffix
float4 bytes0.0fDecimal, use f suffix: 3.14f
double8 bytes0.0Precise decimal (most common)
char2 bytes'\u0000'Single character: 'A', '9'
boolean1 bitfalsetrue or false only

B. Reference Data Types:

Store memory addresses (references) to objects, not the value itself.
Examples: String, Arrays, Objects, Interfaces
// Primitive int age = 25; double price = 99.99; char grade = 'A'; boolean isActive = true; // Reference String name = "Ankush"; int[] numbers = {1, 2, 3, 4, 5}; Student s = new Student();
💡 Key Difference:
Primitive = stores actual value in stack.
Reference = stores address; object lives in heap.

5. Operators in Java

TypeOperatorsExample
Arithmetic+ - * / % ++ --a + b, a % 3, a++
Relational== != > < >= <=a == b, a > 5
Logical&& || !a>0 && b>0
Assignment= += -= *= /=a += 5 (same as a = a+5)
Bitwise& | ^ ~ << >>a & b, a << 2
Ternarycondition ? a : bmax = a>b ? a : b
int a = 10, b = 3; // Arithmetic System.out.println(a + b); // 13 System.out.println(a % b); // 1 (remainder) System.out.println(a++); // 10 (post-increment: use then add) System.out.println(++a); // 12 (pre-increment: add then use) // Ternary int max = (a > b) ? a : b; System.out.println("Max: " + max); // Max: 12 // Logical boolean result = (a > 0) && (b > 0); System.out.println(result); // true

6. Control Statements

1. if-else Statement:
if (condition) { // code if true } else { // code if false } // Example int marks = 85; if (marks >= 75) { System.out.println("Grade A"); } else { System.out.println("Grade B"); }
2. switch Statement:
switch (variable) { case value1: // code break; case value2: // code break; default: // code } // Example int day = 3; switch (day) { case 1: System.out.println("Monday"); break; case 2: System.out.println("Tuesday"); break; case 3: System.out.println("Wednesday"); break; default: System.out.println("Invalid"); }
3. for Loop:
for (initialization; condition; update) { // code } // Example for (int i = 1; i <= 5; i++) { System.out.println(i); }
4. while Loop:
while (condition) { // code } // Example int i = 1; while (i <= 5) { System.out.println(i); i++; }
5. do-while Loop:
do { // code } while (condition); // Example int i = 1; do { System.out.println(i); i++; } while (i <= 5);

7. Arrays

📖 Array: A collection of elements of the same data type stored in contiguous memory locations. Index starts at 0.
// 1D Array int[] marks = new int[5]; // Declare with size int[] scores = {85, 90, 78, 92, 88}; // Declare with values System.out.println(scores[0]); // 85 (first element) System.out.println(scores.length); // 5 // Traverse with loop for (int i = 0; i < scores.length; i++) { System.out.println(scores[i]); } // Enhanced for loop for (int score : scores) { System.out.println(score); } // 2D Array int[][] matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; System.out.println(matrix[1][2]); // 6 (row 1, col 2)
💡 Key Points:
• Arrays are fixed size — cannot grow or shrink
• Index starts at 0, last index = length - 1
• Accessing out-of-bounds index throws ArrayIndexOutOfBoundsException

8. Searching and Sorting

📖 Searching: Finding whether a target value exists in a collection (and where). Sorting: Arranging elements of a collection in a specific order (ascending/descending).

A. Linear Search:

Checks every element one by one from the start until the target is found or the array ends. Works on both sorted and unsorted arrays.
class LinearSearch { static int search(int[] arr, int target) { for (int i = 0; i < arr.length; i++) { if (arr[i] == target) { return i; // found at index i } } return -1; // not found } public static void main(String[] args) { int[] arr = {45, 12, 78, 3, 90, 21}; int result = search(arr, 78); if (result != -1) System.out.println("Found at index: " + result); else System.out.println("Not found"); } } // Output: Found at index: 2
💡 Time Complexity: O(n) worst case — Best case O(1) if element is first.

B. Binary Search:

Works only on a sorted array. Repeatedly divides the search range in half by comparing the middle element to the target.
class BinarySearch { static int search(int[] arr, int target) { int low = 0, high = arr.length - 1; while (low <= high) { int mid = (low + high) / 2; if (arr[mid] == target) { return mid; } else if (arr[mid] < target) { low = mid + 1; // search right half } else { high = mid - 1; // search left half } } return -1; } public static void main(String[] args) { int[] arr = {3, 12, 21, 45, 78, 90}; // must be sorted int result = search(arr, 45); System.out.println("Found at index: " + result); } } // Output: Found at index: 3
💡 Time Complexity: O(log n) — much faster than linear search, but array must be sorted first.

C. Bubble Sort:

Repeatedly compares adjacent elements and swaps them if they are in the wrong order. Largest element "bubbles up" to the end in each pass.
class BubbleSort { static void sort(int[] arr) { int n = arr.length; for (int i = 0; i < n - 1; i++) { for (int j = 0; j < n - 1 - i; j++) { if (arr[j] > arr[j + 1]) { // swap int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } public static void main(String[] args) { int[] arr = {64, 34, 25, 12, 22, 11, 90}; sort(arr); for (int x : arr) System.out.print(x + " "); } } // Output: 11 12 22 25 34 64 90

D. Selection Sort:

Finds the minimum element from the unsorted part and places it at the beginning, one position at a time.
class SelectionSort { static void sort(int[] arr) { int n = arr.length; for (int i = 0; i < n - 1; i++) { int minIndex = i; for (int j = i + 1; j < n; j++) { if (arr[j] < arr[minIndex]) { minIndex = j; } } // swap minimum with first unsorted element int temp = arr[minIndex]; arr[minIndex] = arr[i]; arr[i] = temp; } } public static void main(String[] args) { int[] arr = {29, 10, 14, 37, 13}; sort(arr); for (int x : arr) System.out.print(x + " "); } } // Output: 10 13 14 29 37
AlgorithmBest CaseWorst CaseNeeds Sorted Input?
Linear SearchO(1)O(n)No
Binary SearchO(1)O(log n)Yes
Bubble SortO(n)O(n²)
Selection SortO(n²)O(n²)
💡 Exam Tip:
• Binary search needs a sorted array — always mention that pre-condition.
• Bubble Sort: swaps adjacent elements. Selection Sort: finds min and places it — fewer swaps overall.
• Dry-run one pass of Bubble/Selection sort by hand — a common 5M question.
🔗 Chapter 2 — Java Classes
🔗 JAVA CLASSES - MIND MAP
Abstract Classes → Partial implementation, cannot instantiate directly
Static & Inner Classes → Static (class-level, no outer instance needed), Inner (linked to outer object)
Classes & Constructors → Blueprint for objects, constructors initialize them
Overloading vs Overriding → Compile-time vs runtime polymorphism
Inheritance → Single, Multilevel, Hierarchical, Multiple (via interfaces)
Keywords & Access → this (current object), super (parent), public/protected/default/private

1. Abstract Classes

📖 Abstract Class:
Declared with abstract — cannot create its objects directly. Has abstract methods (no body) + normal methods. Child classes must implement all abstract methods.
💡 Real-life Example:
"Shape" is abstract (you can't draw a generic shape), but Circle and Rectangle are concrete implementations.
abstract class Shape { String color; // Abstract method (no body) abstract void draw(); // Concrete method (has body) void setColor(String color) { this.color = color; System.out.println("Color set to " + color); } } class Circle extends Shape { void draw() { // Must implement System.out.println("Drawing circle"); } } // Shape s = new Shape(); // ERROR! Cannot instantiate Circle c = new Circle(); c.setColor("Red"); c.draw();

2. Static Members & Static Nested Classes

Static Variables & Methods:
📖 Static: Belongs to class, not to individual objects. Shared by all instances.
class Student { String name; // Instance variable static String school; // Static variable (shared) static int count = 0; Student(String n) { name = n; count++; } static void displaySchool() { System.out.println("School: " + school); } } // Usage Student.school = "ABC School"; Student s1 = new Student("Raj"); Student s2 = new Student("Priya"); System.out.println(Student.count); // 2 Student.displaySchool();
💡 Key Points:
• Static members shared by all objects
• Access using ClassName.member
• Static method can access only static members
• Cannot use 'this' in static context
Static Nested Class:
📖 Static Nested Class:
A class inside another class marked with static. Linked to the outer class (not its objects). Can only access static members of the outer class.
class Outer { static int x = 10; int y = 20; static class StaticNested { void display() { System.out.println("x = " + x); // Can access static // System.out.println(y); // ERROR! Cannot access non-static } } } // Creating object Outer.StaticNested obj = new Outer.StaticNested(); obj.display(); // Output: x = 10

3. Inner Classes

Inner Class (Non-static):
📖 Inner Class:
A non-static class inside another class. Linked to an instance of the outer class and can access all its members (static + non-static).
class Outer { int x = 20; class Inner { void display() { System.out.println("x = " + x); // Can access non-static } } } // Creating object (need outer object first) Outer outer = new Outer(); Outer.Inner inner = outer.new Inner(); inner.display(); // Output: x = 20

4. Objects and Classes in Java

📖 Class: Blueprint that defines structure and behavior.
📖 Object: Instance of a class with actual values.
// Class definition class Student { String name; int rollNo; void display() { System.out.println("Name: " + name); System.out.println("Roll No: " + rollNo); } } // Creating objects Student s1 = new Student(); s1.name = "Raj"; s1.rollNo = 101; s1.display();
💡 Class vs Object:
Class = Cookie cutter (template)
Object = Actual cookies (instances)

5. Constructors

📖 Constructor: Special method that initializes objects. Called automatically when object is created using 'new' keyword.
Rules:
• Name = Class name
• No return type
• Called automatically
• Can be overloaded
class Student { String name; int rollNo; // Default constructor Student() { name = "Unknown"; rollNo = 0; } // Parameterized constructor Student(String n, int r) { name = n; rollNo = r; } } // Usage Student s1 = new Student(); Student s2 = new Student("Raj", 101);

6. Methods, Overloading and Overriding

Method Basics:
📖 Method: Block of code that performs specific task. Also called functions.
returnType methodName(parameters) { // code return value; } // Examples class Calculator { int add(int a, int b) { return a + b; } void greet() { System.out.println("Hello!"); } } Calculator calc = new Calculator(); int sum = calc.add(10, 20); calc.greet();
Method Overloading (Compile-time Polymorphism):
📖 Overloading:
Multiple methods with the same name but different parameters in the same class. Compiler picks the right one at compile time. No need for names like addTwoInt(), addThreeInt().
💡 Real-life Analogy:
A calculator can add() two numbers, three numbers, or decimal numbers - same operation name, different inputs. You don't need separate methods like addTwoNumbers(), addThreeNumbers(), addDecimals().
class Calculator { // Overloaded methods - same name, different parameters // Method 1: Two integers int add(int a, int b) { return a + b; } // Method 2: Three integers int add(int a, int b, int c) { return a + b + c; } // Method 3: Two doubles double add(double a, double b) { return a + b; } } Calculator calc = new Calculator(); System.out.println(calc.add(5, 10)); // Calls method 1 → 15 System.out.println(calc.add(5, 10, 15)); // Calls method 2 → 30 System.out.println(calc.add(5.5, 10.5)); // Calls method 3 → 16.0
💡 Overloading Rules:
• Must have different parameter lists (number, type, or order)
• Return type alone is NOT enough to overload
• Can have different access modifiers
• Can throw different exceptions
Method Overriding (Runtime Polymorphism):
📖 Overriding:
Child class redefines a parent method with the exact same name and params. Which version runs is decided at runtime. Lets child classes customize inherited behavior.
💡 Real-life Analogy:
Parent says "go to school by bus" (general instruction), but child overrides with "I'll go by bicycle" - same action (going to school), different implementation. The child customizes the parent's method.
class Animal { // Parent class method void sound() { System.out.println("Animal makes a sound"); } void eat() { System.out.println("Animal eats"); } } class Dog extends Animal { // Overriding parent's sound() method @Override // Annotation (optional but recommended) void sound() { System.out.println("Dog barks: Woof! Woof!"); } // eat() is inherited as-is } class Cat extends Animal { // Overriding parent's sound() method differently @Override void sound() { System.out.println("Cat meows: Meow! Meow!"); } } Animal a = new Dog(); a.sound(); // Output: Dog barks: Woof! Woof! (runtime decision) a.eat(); // Output: Animal eats (inherited)
💡 Overriding Rules:
• Method signature must be exactly same as parent
• Access modifier must be same or less restrictive
• Return type must be same or covariant (subtype)
• Cannot override final, static, or private methods
• @Override annotation helps catch mistakes
Feature Overloading Overriding
Location Same class Parent-child classes
Parameters Must be different Must be exactly same
Binding Compile-time (early) Runtime (late)
Return Type Can be different Same or covariant
Purpose Increase readability Customize behavior

7. Inheritance and Types of Inheritance

📖 Inheritance:
Child class gets all properties and methods of parent using extends, and can add its own. Promotes reusability and IS-A relationship (Dog IS-A Animal).
💡 Real-life Example:
Dog IS-A Animal (inherits eating, breathing) but also has its own features (barking). Car IS-A Vehicle (inherits starting, stopping) but has its own features (4 wheels).
1. Single Inheritance:
One child class inherits from one parent class. A → B
class Vehicle { void start() { System.out.println("Vehicle started"); } } class Car extends Vehicle { void drive() { System.out.println("Car driving"); } } Car c = new Car(); c.start(); // Inherited c.drive(); // Own method
2. Multilevel Inheritance:
Chain of inheritance. A → B → C (B inherits from A, C inherits from B)
class Vehicle { void start() { } } class Car extends Vehicle { void drive() { } } class SportsCar extends Car { void turbo() { } } SportsCar sc = new SportsCar(); sc.start(); // From Vehicle sc.drive(); // From Car sc.turbo(); // Own method
3. Hierarchical Inheritance:
One parent class, multiple child classes. A → B, A → C
class Animal { void eat() { System.out.println("Eating..."); } } class Dog extends Animal { void bark() { System.out.println("Barking..."); } } class Cat extends Animal { void meow() { System.out.println("Meowing..."); } }
4. Multiple Inheritance (Using Interface):
One class inherits from multiple parents. NOT supported with classes (diamond problem) but supported through interfaces.
interface Flyable { void fly(); } interface Swimmable { void swim(); } class Duck implements Flyable, Swimmable { public void fly() { System.out.println("Duck flying"); } public void swim() { System.out.println("Duck swimming"); } }

8. Interface

📖 Interface:
A contract a class must follow. Contains abstract methods (no body). Class uses implements and must define all methods. Achieves 100% abstraction + supports multiple inheritance.
💡 Real-life Example:
TV Remote interface - defines buttons (methods) that any TV must implement, but each TV brand implements them differently.
interface Animal { void eat(); // public abstract (by default) void sleep(); } class Dog implements Animal { public void eat() { System.out.println("Dog eats"); } public void sleep() { System.out.println("Dog sleeps"); } } Dog d = new Dog(); d.eat(); d.sleep();

9. this and Super Keyword

this Keyword:
📖 this keyword:
Refers to the current object. Used to separate instance variables from same-named parameters, and to call another constructor within the same class.
class Student { String name; int age; Student(String name, int age) { this.name = name; // this.name = instance variable this.age = age; // name, age = parameters } Student() { this("Unknown", 0); // Call another constructor } void display() { System.out.println(this.name + ", " + this.age); } }
super Keyword:
📖 super keyword:
Refers to the immediate parent class. Used to call parent's constructor, access parent's variable, or call parent's method when child has same-named members.
class Vehicle { int speed = 50; void display() { System.out.println("Vehicle display"); } } class Car extends Vehicle { int speed = 100; Car() { super(); // Call parent constructor } void show() { System.out.println("Car speed: " + speed); // 100 System.out.println("Vehicle speed: " + super.speed); // 50 super.display(); // Parent method } }

10. Access Control (Access Specifiers)

📖 Access Specifiers: Control visibility and accessibility of class members.
Modifier Class Package Subclass World
public
protected
default
private
class BankAccount { public String accountHolder; private double balance; protected String accountType; int accountNumber; // default public void deposit(double amount) { balance += amount; } }
🛡️ Chapter 3 — Exception Handling
🛡️ EXCEPTION HANDLING - MIND MAP
Packages → Built-in (java.util, java.io...) & User-defined, accessed via import/classpath
Exception Hierarchy → Throwable → Error (unrecoverable) / Exception (Checked & Unchecked)
try-catch-finally → Risky code → Handle error → Always-run cleanup
throw vs throws → throw = actually throwing one; throws = declaring a method might throw
Custom Exceptions → Extend Exception class for application-specific errors

1. Built-in Packages (java.awt, java.io, java.lang, java.math, java.sql, java.util)

📖 What is a Package?
A package is a namespace that organizes related classes and interfaces. It prevents naming conflicts, provides access control, and makes code easier to maintain.
java.lang - Language Package (Automatically Imported):
📖 java.lang:
Automatically imported into every Java program. Contains core classes: String, Math, System, Integer, Thread, Object, Exception.

Key Point: No need to write import java.lang.* - it's automatic!
// java.lang is auto-imported - no import needed! // String class String name = "Ankush"; int length = name.length(); // Math class double result = Math.sqrt(25); // 5.0 int maximum = Math.max(10, 20); // 20 // System class System.out.println("Hello World"); // Wrapper classes Integer num = Integer.parseInt("123"); Double decimal = Double.parseDouble("45.67"); // Object class (parent of all classes) Object obj = new String("test"); Output: Hello World
java.util - Utility Package:
📖 java.util:
Contains utility classes for collections, date/time, random numbers. Must be imported before use.
Common classes: ArrayList, HashMap, Scanner, Date, Random.
import java.util.*; // ArrayList - dynamic array ArrayList fruits = new ArrayList<>(); fruits.add("Apple"); fruits.add("Banana"); fruits.add("Orange"); System.out.println(fruits); // [Apple, Banana, Orange] // HashMap - key-value pairs HashMap marks = new HashMap<>(); marks.put("Raj", 85); marks.put("Priya", 92); System.out.println(marks.get("Raj")); // 85 // Scanner - user input Scanner sc = new Scanner(System.in); System.out.print("Enter name: "); String name = sc.nextLine(); // Date Date today = new Date(); System.out.println(today); // Random Random rand = new Random(); int randomNum = rand.nextInt(100); // 0 to 99
java.io - Input/Output Package:
📖 java.io:
Provides classes for input/output through data streams and file handling.
Common classes: File, FileReader, FileWriter, BufferedReader, PrintWriter.
import java.io.*; // Reading from file try { FileReader fr = new FileReader("data.txt"); BufferedReader br = new BufferedReader(fr); String line; while ((line = br.readLine()) != null) { System.out.println(line); } br.close(); } catch (IOException e) { System.out.println("Error: " + e.getMessage()); } // Writing to file try { FileWriter fw = new FileWriter("output.txt"); PrintWriter pw = new PrintWriter(fw); pw.println("Hello File!"); pw.println("Java is awesome"); pw.close(); System.out.println("File written successfully"); } catch (IOException e) { System.out.println("Error: " + e.getMessage()); }
java.awt - Abstract Window Toolkit:
📖 java.awt:
Contains classes for creating GUI and handling graphics.
Common classes: Frame, Button, Label, TextField, Panel, Color, Font.
import java.awt.*; // Creating a simple window Frame f = new Frame("My First Window"); Button b = new Button("Click Me"); Label l = new Label("Welcome!"); f.add(b); f.add(l); f.setSize(400, 300); f.setLayout(new FlowLayout()); f.setVisible(true); // Output: A window appears with a button and label
java.math - Mathematics Package:
📖 java.math:
Provides classes for arbitrary-precision arithmetic beyond primitive type ranges.
Common classes: BigInteger (large integers), BigDecimal (precise decimals).
💡 Why BigInteger/BigDecimal?
long max: 9,223,372,036,854,775,807
BigInteger max: Unlimited! Can store numbers with millions of digits
BigDecimal: Precise money calculations (no rounding errors)
import java.math.*; // BigInteger - very large numbers BigInteger big1 = new BigInteger("123456789012345678901234567890"); BigInteger big2 = new BigInteger("987654321098765432109876543210"); BigInteger sum = big1.add(big2); BigInteger product = big1.multiply(big2); System.out.println("Sum: " + sum); System.out.println("Product: " + product); // BigDecimal - precise decimal math BigDecimal price1 = new BigDecimal("19.99"); BigDecimal price2 = new BigDecimal("5.01"); BigDecimal total = price1.add(price2); System.out.println("Total: $" + total); // $25.00 (exact!)
java.sql - SQL Package:
📖 java.sql:
Provides classes and interfaces for database access via JDBC.
Common interfaces: Connection, Statement, ResultSet, DriverManager.
import java.sql.*; // Database connection and query try { // 1. Load driver (automatic in modern Java) // 2. Establish connection Connection con = DriverManager.getConnection( "jdbc:mysql://localhost:3306/college", "root", "password" ); // 3. Create statement Statement stmt = con.createStatement(); // 4. Execute query ResultSet rs = stmt.executeQuery("SELECT * FROM students"); // 5. Process results while (rs.next()) { int id = rs.getInt("id"); String name = rs.getString("name"); int marks = rs.getInt("marks"); System.out.println(id + " | " + name + " | " + marks); } // 6. Close connection con.close(); } catch (SQLException e) { System.out.println("Database Error: " + e.getMessage()); } Output: 1 | Raj | 85 2 | Priya | 92 3 | Amit | 78
💡 Package Summary:
java.lang - Core (String, Math, System) - AUTO IMPORTED
java.util - Utilities (ArrayList, HashMap, Scanner)
java.io - File I/O (FileReader, FileWriter)
java.awt - GUI (Frame, Button, Label)
java.math - Big Numbers (BigInteger, BigDecimal)
java.sql - Database (Connection, Statement, ResultSet)

2. Creating User Defined Packages

📖 Definition:
User-defined packages are custom packages created by programmers. The 'package' keyword must be the first statement in a Java source file.

Why? Code organization, avoid naming conflicts, access control.
💡 Analogy: Like company departments: com.company.hr (HR classes), com.company.finance (Finance classes), com.company.sales (Sales classes).
Steps to Create a Package:
1. Declare package: package packagename; (first line)
2. Write your class code
3. Save file: ClassName.java
4. Compile: javac -d . FileName.java
5. Directory structure automatically created
// File: Student.java // Step 1: Package declaration (MUST be first) package college.students; // Step 2: Imports (if needed) import java.util.*; // Step 3: Class definition public class Student { private String name; private int rollNo; public Student(String name, int rollNo) { this.name = name; this.rollNo = rollNo; } public void display() { System.out.println("Name: " + name); System.out.println("Roll No: " + rollNo); } } // Compile command: // javac -d . Student.java // Directory structure created: // college/ // students/ // Student.class
Sub-packages (Nested Packages):
📖 Sub-packages:
Packages within packages, creating a hierarchy. Use dots (.) to separate levels.
Example: college.students.engineering (3 levels)
// File: CSEStudent.java package college.students.engineering.cse; public class CSEStudent { String branch = "Computer Science"; String semester = "5th"; public void showDetails() { System.out.println("Branch: " + branch); System.out.println("Semester: " + semester); } } // Directory structure: // college/ // students/ // engineering/ // cse/ // CSEStudent.class
💡 Package Naming Conventions:
• Use lowercase letters only
• Reverse domain name: com.company.project
• Avoid Java keywords (int, class, public, etc.)
• Use dots to separate levels
• Example: com.ankushraj.notes.java
// Good package names: package com.company.project.module; package edu.university.department; package org.opensource.library; // Bad package names: package MyPackage; // Capital letters package com.company.class; // 'class' is keyword package 123project; // Starts with number

3. Accessing a Package

📖 Definition:
To use classes from another package, you must make them accessible via import statement (recommended) or fully qualified name.
Method 1: Using import Statement:
Import specific class: import packagename.ClassName;
Import all classes: import packagename.*;
// Import specific class import java.util.ArrayList; import college.students.Student; public class Main { public static void main(String[] args) { ArrayList list = new ArrayList<>(); // OK Student s = new Student("Raj", 101); // OK s.display(); } } // Import all classes from package import java.util.*; public class Test { public static void main(String[] args) { ArrayList list = new ArrayList<>(); // OK HashMap map = new HashMap<>(); // OK Scanner sc = new Scanner(System.in); // OK } }
Method 2: Fully Qualified Name:
📖 Fully Qualified Name:
Using the complete package path before the class name, without import.
When to use: When two classes have the same name from different packages.
// No import needed - use full package path public class Main { public static void main(String[] args) { // Full package path java.util.ArrayList list = new java.util.ArrayList<>(); college.students.Student s = new college.students.Student("Raj", 101); } } // Solving name conflicts public class DateExample { public static void main(String[] args) { // Both packages have Date class! java.util.Date utilDate = new java.util.Date(); // Current date java.sql.Date sqlDate = new java.sql.Date(System.currentTimeMillis()); // SQL date System.out.println("Util Date: " + utilDate); System.out.println("SQL Date: " + sqlDate); } }
Static Import:
📖 Static Import:
Imports static members directly so they can be used without the class name prefix.
Syntax: import static packagename.ClassName.memberName;
// Without static import public class Test1 { public static void main(String[] args) { System.out.println(Math.PI); // Need Math. System.out.println(Math.max(10, 20)); // Need Math. System.out.println(Math.sqrt(25)); // Need Math. } } // With static import import static java.lang.Math.*; // Import all static members public class Test2 { public static void main(String[] args) { System.out.println(PI); // Direct use! System.out.println(max(10, 20)); // Direct use! System.out.println(sqrt(25)); // Direct use! } } Output (both programs): 3.141592653589793 20 5.0
💡 Import Best Practices:
• Use specific imports when possible: import java.util.ArrayList;
• Use import package.*; for multiple classes from same package
• Use fully qualified names only for name conflicts
• Static import: use sparingly (can make code confusing)

4. Using a Package

📖 Definition:
Once imported, package classes are used like built-in classes. CLASSPATH tells Java where to find packages.
CLASSPATH: List of directories/JAR files where Java searches for classes.
💡 Complete Example: Creating and Using Custom Package
// Step 1: Create package class // File: Calculator.java package mypackage.utils; public class Calculator { public int add(int a, int b) { return a + b; } public int subtract(int a, int b) { return a - b; } public int multiply(int a, int b) { return a * b; } } // Compile: // javac -d . Calculator.java // Creates: mypackage/utils/Calculator.class
// Step 2: Use package in another program // File: Main.java import mypackage.utils.Calculator; public class Main { public static void main(String[] args) { Calculator calc = new Calculator(); System.out.println("10 + 5 = " + calc.add(10, 5)); System.out.println("10 - 5 = " + calc.subtract(10, 5)); System.out.println("10 * 5 = " + calc.multiply(10, 5)); } } // Compile: // javac Main.java // Run: // java Main Output: 10 + 5 = 15 10 - 5 = 5 10 * 5 = 50
Setting CLASSPATH:
// Windows: set CLASSPATH=.;C:\myproject\classes;C:\libraries\lib.jar // Linux/Mac: export CLASSPATH=.:/home/user/myproject/classes:/libs/lib.jar // In Java command: java -cp .:/path/to/classes Main // Dot (.) means current directory

5. Exception Objects & Exception Hierarchy

📖 What is an Exception?
An abnormal event or runtime error that disrupts the normal flow of program execution. Without handling, the program terminates abruptly.

Why handle? Prevents crashes, maintains flow, provides user-friendly error messages, ensures resource cleanup.
💡 Analogy: Like a flat tire while driving — exception handling means stopping safely and fixing it instead of crashing.
Exception Hierarchy:
Object (parent of all) └── Throwable ├── Error (serious problems - NOT handled) │ ├── OutOfMemoryError │ └── StackOverflowError │ └── Exception (handled by programmers) ├── IOException (Checked) ├── SQLException (Checked) └── RuntimeException (Unchecked) ├── NullPointerException ├── ArithmeticException ├── ArrayIndexOutOfBoundsException └── NumberFormatException
Two types of Exceptions:
1. Checked Exceptions: Checked at compile-time. Must handle with try-catch or throws.
2. Unchecked Exceptions: Checked at runtime. Handling optional (but recommended).
Common Built-in Exceptions:
1. NullPointerException:
Occurs when trying to use a null object reference.
String name = null; System.out.println(name.length()); // NullPointerException! // Output: Exception in thread "main" java.lang.NullPointerException // Fix: if (name != null) { System.out.println(name.length()); } else { System.out.println("Name is null"); }
2. ArithmeticException:
Occurs during mathematical operations (like division by zero).
int a = 10, b = 0; int result = a / b; // ArithmeticException: / by zero // Fix: if (b != 0) { int result = a / b; System.out.println("Result: " + result); } else { System.out.println("Cannot divide by zero"); }
3. ArrayIndexOutOfBoundsException:
Occurs when accessing array with invalid index (negative or >= array length).
int[] arr = {10, 20, 30}; System.out.println(arr[5]); // ArrayIndexOutOfBoundsException! // Fix: int index = 5; if (index >= 0 && index < arr.length) { System.out.println(arr[index]); } else { System.out.println("Invalid index: " + index); }
4. NumberFormatException:
Occurs when converting invalid string to number.
String str = "abc"; int num = Integer.parseInt(str); // NumberFormatException! // Fix: try { int num = Integer.parseInt(str); System.out.println("Number: " + num); } catch (NumberFormatException e) { System.out.println("Invalid number format: " + str); }
5. FileNotFoundException (Checked Exception):
Occurs when trying to access a file that doesn't exist. Must handle.
import java.io.*; // Must handle - compiler forces you! try { FileReader fr = new FileReader("nonexistent.txt"); } catch (FileNotFoundException e) { System.out.println("File not found: " + e.getMessage()); }
Exception Cause Type
NullPointerException Using null object Unchecked
ArithmeticException Division by zero Unchecked
ArrayIndexOutOfBoundsException Invalid array index Unchecked
NumberFormatException Invalid string to number Unchecked
FileNotFoundException File doesn't exist Checked
IOException I/O operation failed Checked
💡 Remember:
Checked: Compiler checks - MUST handle
Unchecked: Runtime checks - SHOULD handle
• All inherit from Exception class
• Use try-catch to handle exceptions

6. try and catch — Handling Exceptions

📖 Multiple Exception Handling:
Use multiple catch blocks to handle different exception types differently from a single try block.

Why? Different exceptions need different handling logic and error messages.
Method 1: Multiple Catch Blocks:
public class MultipleCatchExample { public static void main(String[] args) { try { int[] arr = {10, 20, 30}; // Can throw ArrayIndexOutOfBoundsException System.out.println(arr[5]); // Can throw ArithmeticException int result = 10 / 0; // Can throw NullPointerException String name = null; System.out.println(name.length()); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Error: Invalid array index"); System.out.println("Details: " + e.getMessage()); } catch (ArithmeticException e) { System.out.println("Error: Mathematical error"); System.out.println("Details: " + e.getMessage()); } catch (NullPointerException e) { System.out.println("Error: Null value encountered"); System.out.println("Details: " + e.getMessage()); } System.out.println("Program continues..."); } } Output: Error: Invalid array index Details: Index 5 out of bounds for length 3 Program continues...
Method 2: Multi-catch Block (Java 7+):
📖 Multi-catch:
Handle multiple exception types with same logic using single catch block. Exceptions separated by pipe (|) symbol.
public class MultiCatchExample { public static void main(String[] args) { try { String input = "abc"; int num = Integer.parseInt(input); // NumberFormatException int[] arr = {1, 2, 3}; System.out.println(arr[10]); // ArrayIndexOutOfBoundsException } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { // Same handling for both exceptions System.out.println("Error occurred: " + e.getClass().getSimpleName()); System.out.println("Message: " + e.getMessage()); } System.out.println("Program continues..."); } } Output: Error occurred: NumberFormatException Message: For input string: "abc" Program continues...
Catch Order Rules:
📖 Important Rule:
Catch blocks must be ordered from most specific to most general. Child exception must be caught before parent exception.
// CORRECT order - specific to general try { // code } catch (ArrayIndexOutOfBoundsException e) { // Specific System.out.println("Array error"); } catch (RuntimeException e) { // General (parent) System.out.println("Runtime error"); } catch (Exception e) { // Most general System.out.println("General error"); } // WRONG order - will not compile! try { // code } catch (Exception e) { // Most general first System.out.println("General error"); } catch (ArrayIndexOutOfBoundsException e) { // Unreachable! System.out.println("Array error"); // Compiler error! }
Complete Example - File Reading with Multiple Exceptions:
import java.io.*; public class FileReadMultipleCatch { public static void main(String[] args) { BufferedReader br = null; try { // Can throw FileNotFoundException br = new BufferedReader(new FileReader("data.txt")); // Can throw IOException String line = br.readLine(); System.out.println("First line: " + line); // Can throw NumberFormatException int number = Integer.parseInt(line); System.out.println("Number: " + number); // Can throw ArithmeticException int result = 100 / number; System.out.println("Result: " + result); } catch (FileNotFoundException e) { System.out.println("File not found: " + e.getMessage()); } catch (IOException e) { System.out.println("Error reading file: " + e.getMessage()); } catch (NumberFormatException e) { System.out.println("Invalid number format: " + e.getMessage()); } catch (ArithmeticException e) { System.out.println("Mathematical error: " + e.getMessage()); } catch (Exception e) { // Generic catch for any other exception System.out.println("Unexpected error: " + e.getMessage()); } finally { // Cleanup code (discussed in next section) try { if (br != null) { br.close(); } } catch (IOException e) { System.out.println("Error closing file"); } } } }
💡 Best Practices:
• Order catch blocks from specific to general
• Use multi-catch for same handling logic
• Always have a generic Exception catch at end (optional)
• Don't catch Exception too early - masks specific errors
• Log exception details for debugging

7. The finally Block

📖 What is finally Block?
A block that always executes regardless of exception occurrence. Used for cleanup (closing files, connections).

Executes: After try (no exception), after catch (exception handled), even with return statement.
Syntax:
try { // Code that may throw exception } catch (ExceptionType e) { // Handle exception } finally { // Always executes (cleanup code) }
Example 1: finally Always Executes:
public class FinallyExample1 { public static void main(String[] args) { System.out.println("Start"); try { System.out.println("Inside try block"); int result = 10 / 2; // No exception System.out.println("Result: " + result); } catch (ArithmeticException e) { System.out.println("Inside catch block"); } finally { System.out.println("Inside finally block - ALWAYS executes"); } System.out.println("End"); } } Output: Start Inside try block Result: 5 Inside finally block - ALWAYS executes End
Example 2: finally with Exception:
public class FinallyExample2 { public static void main(String[] args) { System.out.println("Start"); try { System.out.println("Inside try block"); int result = 10 / 0; // ArithmeticException! System.out.println("This won't execute"); } catch (ArithmeticException e) { System.out.println("Inside catch block: " + e.getMessage()); } finally { System.out.println("Inside finally block - ALWAYS executes"); } System.out.println("End"); } } Output: Start Inside try block Inside catch block: / by zero Inside finally block - ALWAYS executes End
Example 3: finally with return Statement:
public class FinallyWithReturn { public static int testFinally() { try { System.out.println("Inside try"); return 10; // Will return, but finally executes first! } catch (Exception e) { System.out.println("Inside catch"); return 20; } finally { System.out.println("Inside finally - executes even with return!"); } } public static void main(String[] args) { int result = testFinally(); System.out.println("Returned value: " + result); } } Output: Inside try Inside finally - executes even with return! Returned value: 10
Practical Use Case - File Handling:
import java.io.*; public class FinallyFileExample { public static void main(String[] args) { BufferedReader br = null; try { br = new BufferedReader(new FileReader("data.txt")); String line = br.readLine(); System.out.println("Data: " + line); // Some processing that may throw exception int num = Integer.parseInt(line); System.out.println("Number: " + num); } catch (FileNotFoundException e) { System.out.println("File not found"); } catch (IOException e) { System.out.println("Error reading file"); } catch (NumberFormatException e) { System.out.println("Invalid number"); } finally { // ALWAYS close the file - cleanup code System.out.println("Closing file..."); try { if (br != null) { br.close(); System.out.println("File closed successfully"); } } catch (IOException e) { System.out.println("Error closing file"); } } System.out.println("Program ends"); } }
💡 When finally doesn't execute:
Only 4 rare cases:
• System.exit() called
• JVM crash
• Thread death
• Infinite loop in try/catch
💡 finally vs try-with-resources:
Java 7+ provides try-with-resources that auto-closes resources:
// Old way with finally BufferedReader br = null; try { br = new BufferedReader(new FileReader("file.txt")); } finally { if (br != null) br.close(); } // New way - try-with-resources (preferred) try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) { // Use br - automatically closed! }

8. throw and throws

📖 What is throws keyword?
Declares in method signature that a method can throw exceptions. Delegates handling to the caller.

throw vs throws:
throw: Actually throws an exception (inside method body)
throws: Declares possible exceptions (in method signature)
Syntax:
returnType methodName(parameters) throws Exception1, Exception2 { // Method body // May throw Exception1 or Exception2 }
Example 1: Basic throws:
import java.io.*; class FileProcessor { // Declares that this method can throw IOException public static void readFile(String filename) throws IOException { FileReader fr = new FileReader(filename); // May throw IOException BufferedReader br = new BufferedReader(fr); String line = br.readLine(); System.out.println("Data: " + line); br.close(); } } public class ThrowsExample1 { public static void main(String[] args) { try { // Caller must handle the declared exception FileProcessor.readFile("data.txt"); } catch (IOException e) { System.out.println("Error: " + e.getMessage()); } } }
Example 2: Multiple throws:
class Calculator { // Declares multiple possible exceptions public static int divide(String num1, String num2) throws NumberFormatException, ArithmeticException { int a = Integer.parseInt(num1); // May throw NumberFormatException int b = Integer.parseInt(num2); return a / b; // May throw ArithmeticException } } public class ThrowsExample2 { public static void main(String[] args) { try { int result = Calculator.divide("10", "2"); System.out.println("Result: " + result); result = Calculator.divide("10", "0"); // Will throw } catch (NumberFormatException e) { System.out.println("Invalid number: " + e.getMessage()); } catch (ArithmeticException e) { System.out.println("Math error: " + e.getMessage()); } } } Output: Result: 5 Math error: / by zero
throws in Method Chain:
import java.io.*; class FileHandler { // Method 1 declares exception public static void processFile() throws IOException { readFile(); // Calling method that throws } // Method 2 declares exception public static void readFile() throws IOException { FileReader fr = new FileReader("data.txt"); // Reading code fr.close(); } } public class ThrowsChain { public static void main(String[] args) { try { // Final caller handles the exception FileHandler.processFile(); } catch (IOException e) { System.out.println("File error: " + e.getMessage()); } } }
throw vs throws - Complete Comparison:
Feature throw throws
Purpose Throw exception explicitly Declare possible exceptions
Location Inside method body Method signature
Syntax throw new Exception(); void m() throws Exception
Number One exception at a time Multiple exceptions (comma-separated)
Followed by Exception object Exception class name
Combined Example - throw with throws:
class VoterValidator { // Declares that method can throw exception public static void checkEligibility(int age) throws Exception { if (age < 18) { // Actually throws the exception throw new Exception("Not eligible. Age: " + age); } System.out.println("Eligible to vote. Age: " + age); } } public class ThrowVsThrows { public static void main(String[] args) { try { VoterValidator.checkEligibility(20); // OK VoterValidator.checkEligibility(15); // Will throw } catch (Exception e) { System.out.println("Error: " + e.getMessage()); } } } Output: Eligible to vote. Age: 20 Error: Not eligible. Age: 15
💡 Key Points:
throws is a warning - "this method might throw exception"
• Caller must handle (try-catch) or propagate (throws again)
• Used with checked exceptions (mandatory)
• Optional for unchecked exceptions
• Can declare parent exception to cover multiple child exceptions

9. User Defined Exceptions

📖 What are User-defined Exceptions?
Custom exception classes created by extending Exception (checked) or RuntimeException (unchecked) for application-specific error handling.

Why? Better error categorization, domain-specific messages, easier debugging.
💡 Example: Banking app needs InsufficientFundsException, InvalidAccountException — built-in exceptions can't describe these specific errors.
Steps to Create User-defined Exception:
1. Create a class extending Exception (or RuntimeException)
2. Create constructors (default & parameterized)
3. Throw the exception using 'throw' keyword
4. Handle using try-catch
Example 1: Age Validation Exception:
// Step 1: Create custom exception class class InvalidAgeException extends Exception { // Default constructor public InvalidAgeException() { super("Invalid age provided"); } // Parameterized constructor public InvalidAgeException(String message) { super(message); } } // Step 2: Use in program class AgeValidator { public static void checkAge(int age) throws InvalidAgeException { if (age < 18) { throw new InvalidAgeException("Age must be 18 or above. You are: " + age); } System.out.println("Age verified: " + age); } } // Step 3: Handle exception public class Main { public static void main(String[] args) { try { AgeValidator.checkAge(15); // Will throw exception } catch (InvalidAgeException e) { System.out.println("Error: " + e.getMessage()); } } } Output: Error: Age must be 18 or above. You are: 15
Example 2: Bank Account Exception:
// Custom exception for insufficient balance class InsufficientFundsException extends Exception { private double amount; public InsufficientFundsException(double amount) { super("Insufficient funds. Need: " + amount); this.amount = amount; } public double getAmount() { return amount; } } // Bank account class class BankAccount { private double balance; public BankAccount(double balance) { this.balance = balance; } public void withdraw(double amount) throws InsufficientFundsException { if (amount > balance) { double shortage = amount - balance; throw new InsufficientFundsException(shortage); } balance -= amount; System.out.println("Withdrawal successful. New balance: " + balance); } public double getBalance() { return balance; } } // Using the custom exception public class BankDemo { public static void main(String[] args) { BankAccount account = new BankAccount(5000); try { System.out.println("Current balance: " + account.getBalance()); account.withdraw(3000); // OK account.withdraw(4000); // Will throw exception } catch (InsufficientFundsException e) { System.out.println("Transaction failed: " + e.getMessage()); System.out.println("Short by: " + e.getAmount()); } } } Output: Current balance: 5000.0 Withdrawal successful. New balance: 2000.0 Transaction failed: Insufficient funds. Need: 2000.0 Short by: 2000.0
Checked vs Unchecked Custom Exceptions:
// Checked exception (extends Exception) class InvalidEmailException extends Exception { public InvalidEmailException(String message) { super(message); } } // Unchecked exception (extends RuntimeException) class InvalidPasswordException extends RuntimeException { public InvalidPasswordException(String message) { super(message); } } // Usage difference class UserValidator { // Checked - must declare with 'throws' public static void validateEmail(String email) throws InvalidEmailException { if (!email.contains("@")) { throw new InvalidEmailException("Email must contain @"); } } // Unchecked - 'throws' optional public static void validatePassword(String password) { if (password.length() < 8) { throw new InvalidPasswordException("Password too short"); } } }
💡 Best Practices:
• Use meaningful exception names (suffixed with "Exception")
• Provide detailed error messages
• Extend Exception for checked, RuntimeException for unchecked
• Include relevant data in exception (like amount, age, etc.)
• Document when exceptions are thrown
Ready for Exam? Sab padh liya? Ab Quick Revision karo — formulas, key points aur common mistakes ek jagah! Quick Revision Karo →
Quick Revision — Last Minute Exam Prep!
📌 How to Use: Read this 5-10 minutes before exam. Contains all important points in condensed form. Focus on tables, comparisons, and PYQ topics!

☕ new Keyword (2M)

Purpose of 'new':
1. Allocates memory in heap
2. Creates object instance
3. Calls constructor
4. Returns reference

Syntax: ClassName obj = new ClassName();

📦 Class vs Object (2M)

Class | Object ------------------- | ------------------- Blueprint/Template | Instance Logical entity | Physical entity No memory | Memory allocated Defined once | Can create many class Student { } | Student s = new Student(); "Car" concept | "My red Toyota"
Exam Trick: Class = Blueprint, Object = Instance (B vs I)

💾 Static vs Non-Static (2M)

Static Members | Non-Static Members ---------------------- | ---------------------- Belong to class | Belong to object Method Area | Heap Memory One copy (shared) | Separate per object When class loads | When object created ClassName.member | objectName.member static int count; | int age;
Rules:
• Static CAN access static only
• Static CANNOT access non-static directly
• Non-static CAN access both
• No 'this' or 'super' in static
Remember S.H.A.R.E: Static = Held in method Area, Reused by Everyone

🔄 Overloading vs Overriding (IMP!)

Overloading | Overriding --------------------- | --------------------- Same class | Parent-child classes Different parameters | Same signature Compile-time | Runtime Can change return | Same return type No inheritance needed | Inheritance required add(int,int) | Parent: show() add(double,double) | Child: show()
Trick:
Overloading = Same NAME, Different PARAMS
Overriding = Different CLASS, Same SIGNATURE

🔗 Inheritance Types

Single: A → B
Multilevel: A → B → C
Hierarchical: A → B, A → C
Multiple: NOT with classes (use Interface)
Hybrid: NOT with classes
Syntax: class Child extends Parent { }

👆 this vs super

this (current object) | super (parent class) --------------------- | ---------------------- this.variable | super.variable this() | super() this (pass object) | super.method() Same class reference | Parent class reference
Rules:
• super() must be FIRST in constructor
• Cannot use both super() and this() together

🎭 Abstract vs Interface (IMP!)

Abstract Class | Interface --------------------- | --------------------- abstract keyword | interface keyword 0-100% abstraction | 100% abstraction Can have constructors | No constructors extends (single) | implements (multiple) Any access modifier | Only public Can have variables | Only constants (final) abstract + concrete | Only abstract (before Java 8)
abstract class Animal { abstract void sound(); void sleep() { } } interface Flyable { void fly(); // public abstract }

📦 Built-in Packages (2M)

6 Built-in Packages:
1. java.lang — Auto-imported. String, Math, System, Object
2. java.util — ArrayList, HashMap, Scanner, Date
3. java.io — FileReader, FileWriter, BufferedReader, PrintWriter
4. java.awt — GUI: Frame, Button, Label, TextField
5. java.math — BigInteger, BigDecimal
6. java.sql — Connection, Statement, ResultSet
Exam Trick: java.lang is auto-imported, rest need import statement

📁 User-Defined Package (2M)

Steps to create:
1. Write package name; at top of file
2. Compile: javac -d . FileName.java
3. Import: import packagename.ClassName;
package mypack; public class Calculator { public int add(int a, int b) { return a + b; } } // Compile: javac -d . Calculator.java // Use: import mypack.Calculator;

🔑 4 Ways to Access Package

1. Specific import: import java.util.ArrayList;
2. Wildcard import: import java.util.*;
3. Fully qualified: java.util.ArrayList list = new java.util.ArrayList();
4. Static import: import static java.lang.Math.*; — use sqrt(), pow() directly

🔍 Searching & Sorting (2M/5M)

Linear Search | O(n) | Any array Binary Search | O(log n) | SORTED array only Bubble Sort | O(n^2) | Swap adjacent pairs Selection Sort | O(n^2) | Pick min, place at front
Exam Trick: Binary search MUST have sorted input — always state this precondition first.

⚠️ Checked vs Unchecked (PYQ!)

Checked | Unchecked --------------------- | --------------------- Compile-time check | Runtime only Must handle (forced) | Optional to handle Exception class | RuntimeException class External factors | Programming errors IOException | NullPointerException SQLException | ArrayIndexOutOfBounds FileNotFoundException | ArithmeticException
C.O.R.T Trick:
Checked: Compile-time, Outside control
Unchecked: Runtime, Typically programmer fault

🛡️ Why Catch Exceptions? (2M)

Prevents program crash
Maintains normal flow
User-friendly error messages
Resource cleanup (finally)
Debugging information
Professional code quality
try { // Risky code } catch (Exception e) { // Handle error } finally { // Always executes (cleanup) }

🎯 throw vs throws (5M PYQ!)

throw | throws --------------------- | --------------------- Inside method body | Method signature Throw exception | Declare exception Exception object | Exception class One at a time | Multiple allowed throw new Exception() | void m() throws Exception Creates & throws | Only declares
Example: void withdraw(int amt) throws InsufficientFundsException { if (amt > balance) { throw new InsufficientFundsException("Low balance"); } }
Memory Trick:
throw = action (doing it)
throws = declaration (warning about it)

⚠️ Common Exam Mistakes

❌ Overriding static/final/private methods
❌ Using 'this' or 'super' in static
❌ Multiple inheritance with classes
❌ Creating object of abstract class/interface
❌ Empty catch blocks (bad practice)
❌ Not handling checked exceptions
❌ Forgetting @Override annotation
❌ Confusing throw vs throws

💻 Must Practice Programs

1. Method overloading example (Calculator)
2. Method overriding (Animal → Dog/Cat)
3. Single, multilevel, hierarchical inheritance
4. Abstract class implementation
5. Interface with multiple implementation
6. this and super keyword usage
7. Static vs non-static demonstration
8. Exception handling (try-catch-finally)
9. throw vs throws example
10. Custom exception creation

✅ Pre-Exam Checklist

☑ new keyword purpose (3 points)
☑ Class vs Object table
☑ Static vs Non-static table
☑ Overloading vs Overriding table
☑ Inheritance types (3 supported, 2 not)
☑ this vs super usage
☑ Abstract vs Interface table
☑ final keyword (3 uses)
☑ Checked vs Unchecked table
☑ Why catch exceptions (6 reasons)
☑ throw vs throws table
☑ Common mistakes list

🎯 Exam Strategy

2 Mark Questions:
• 2-3 sentences or 3-4 points
• Time: 3-4 minutes max
• Add example if time permits

5 Mark Questions:
• Definition + Explanation + Code + Diagram
• Time: 7-8 minutes
• Draw comparison tables when asked "differentiate"

Code Questions:
• Write proper syntax
• Add comments
• Show output if asked
• Use meaningful variable names
🌟 All the Best!
Java is practice-based! Don't just read—write code. The more you code, the better you understand. Remember all comparisons (tables), practice all programs, and you're ready! 💪☕
📄 Previous Year Questions

Section A — 2 Marks PYQs

2M PYQ
Q1. State the purpose of the 'new' keyword in Java.
Answer:

The new keyword in Java is used to create objects (instances) of a class. Its main purposes are:

1. Memory Allocation: Allocates memory dynamically in the heap for the object.

2. Object Creation: Creates an instance of the class with its own copy of instance variables.

3. Constructor Invocation: Automatically calls the constructor to initialize the object.

4. Returns Reference: Returns the memory reference (address) of the newly created object.

Example:
Student s = new Student(); // new allocates memory, calls constructor, returns reference
Without new, you cannot create objects in Java (except for String and primitives which have special handling).
2M PYQ
Q2. Compare a class and an object with differences and examples.
Answer:

Class: A blueprint or template that defines the structure and behavior of objects.
Object: An instance of a class with actual values.

Key Differences:

1. Nature:
• Class: Logical entity (concept)
• Object: Physical entity (real)

2. Memory:
• Class: No memory allocated
• Object: Memory allocated when created

3. Creation:
• Class: Defined using 'class' keyword
• Object: Created using 'new' keyword

4. Count:
• Class: Defined only once
• Object: Can create multiple objects

Example:
// Class - Blueprint class Student { String name; int rollNo; } // Objects - Instances Student s1 = new Student(); // Object 1 s1.name = "Raj"; Student s2 = new Student(); // Object 2 s2.name = "Priya";
Real-life: Class = "Car" (general concept), Object = "My red Toyota" (specific car)
2M PYQ
Q3. Explain memory management for static vs. non-static members in Java.
Answer:

Static Members (Class Level):
• Stored in Method Area (class memory)
• Allocated when class loads (only once)
• Shared by all objects
• Single copy exists for entire class
• Accessed using ClassName.member

Non-Static Members (Object Level):
• Stored in Heap Memory (object memory)
• Allocated when object is created (each time)
• Separate copy for each object
• Independent values per object
• Accessed using objectName.member

Example:
class Student { static String school; // Static - shared by all String name; // Non-static - separate per object } Student.school = "ABC"; // One copy for all Student s1 = new Student(); s1.name = "Raj"; // s1's own copy Student s2 = new Student(); s2.name = "Priya"; // s2's own copy
Key Point: Static members save memory as only one copy exists, while non-static members allow each object to have unique values.
2M PYQ
Q4. Define checked and unchecked exceptions.
Answer:

Checked Exceptions:
Exceptions that are checked at COMPILE TIME. The compiler forces you to handle them using try-catch or throws. If not handled, the program won't compile.

• Checked at: Compile time
• Handling: Mandatory (must handle)
• Extends: Exception class
• Cause: External factors (file, network, database)
• Examples: IOException, FileNotFoundException, SQLException

Unchecked Exceptions:
Exceptions that occur at RUNTIME due to programming errors. Also called Runtime Exceptions. Compiler doesn't force handling.

• Checked at: Runtime
• Handling: Optional
• Extends: RuntimeException class
• Cause: Programming errors
• Examples: NullPointerException, ArrayIndexOutOfBoundsException, ArithmeticException

Simple Rule:
Checked = Compiler checks, must handle
Unchecked = Runtime only, optional handling
2M PYQ
Q5. Explain why catching exceptions is recommended in Java.
Answer:

Catching exceptions is recommended because:

1. Prevents Program Crash: Program doesn't terminate abruptly when error occurs.

2. Maintains Normal Flow: Remaining code continues to execute after handling the exception.

3. User-Friendly Messages: Provides meaningful error messages instead of technical stack traces.

4. Resource Cleanup: Using finally block ensures resources (files, connections) are properly closed even if error occurs.

5. Debugging Information: Can log exception details for troubleshooting.

6. Professional Code: Production-ready applications must handle errors gracefully.

Example:
// Without handling - CRASH int result = 10 / 0; // ArithmeticException, program stops // With handling - CONTINUES try { int result = 10 / 0; } catch (ArithmeticException e) { System.out.println("Cannot divide by zero"); } System.out.println("Program continues...");

Section B — 5 Marks PYQs

5M PYQ
Q1. Demonstrate how Java supports multiple inheritance using interfaces by implementing a Java program that involves two interfaces and a class. Apply the concept to show why interfaces are preferred over multiple class inheritance in Java.
Answer:

Multiple Inheritance Problem:
Java does NOT support multiple inheritance with classes to avoid the "Diamond Problem" (ambiguity when both parent classes have the same method). However, Java achieves multiple inheritance through INTERFACES.

Why Interfaces are Preferred:
1. No ambiguity - all methods are abstract, must be implemented by class
2. Avoids diamond problem
3. A class can implement multiple interfaces
4. Provides flexibility and multiple behavior support

Program Demonstration:
// Interface 1 interface Flyable { void fly(); int MAX_ALTITUDE = 10000; // constant } // Interface 2 interface Swimmable { void swim(); int MAX_DEPTH = 500; // constant } // Class implementing both interfaces (Multiple Inheritance) class Duck implements Flyable, Swimmable { private String name; Duck(String name) { this.name = name; } // Must implement fly() from Flyable public void fly() { System.out.println(name + " is flying"); System.out.println("Max altitude: " + MAX_ALTITUDE); } // Must implement swim() from Swimmable public void swim() { System.out.println(name + " is swimming"); System.out.println("Max depth: " + MAX_DEPTH); } void displayInfo() { System.out.println("I am a " + name); } } // Main class class Main { public static void main(String[] args) { Duck duck = new Duck("Donald Duck"); duck.displayInfo(); // I am a Donald Duck duck.fly(); // Donald Duck is flying duck.swim(); // Donald Duck is swimming // Duck has behavior from both interfaces System.out.println("Duck supports multiple inheritance!"); } } Output: I am a Donald Duck Donald Duck is flying Max altitude: 10000 Donald Duck is swimming Max depth: 500 Duck supports multiple inheritance!
Explanation:
• Duck class implements both Flyable and Swimmable interfaces
• This is multiple inheritance - one class inheriting from multiple sources
• Duck must implement all methods from both interfaces
• No ambiguity because all interface methods are abstract
• Class decides the implementation, avoiding conflicts

Why Not Multiple Class Inheritance:
// This is NOT allowed in Java class A { void show() { System.out.println("A"); } } class B { void show() { System.out.println("B"); } } // ERROR! Cannot extend multiple classes // class C extends A, B { } // Which show() to inherit? Ambiguity!
Conclusion:
Interfaces solve multiple inheritance by requiring the implementing class to provide all method implementations, eliminating ambiguity while providing flexibility to inherit behavior from multiple sources.
5M PYQ
Q2. Differentiate between 'throw' and 'throws' with example code.
Answer:

Difference Between throw and throws:

Aspect throw throws
Purpose Throw exception explicitly Declare possible exceptions
Location Inside method body Method signature
Followed By Exception object (instance) Exception class (type)
Count One exception at a time Multiple exceptions allowed
Syntax throw new Exception(); void method() throws Exception
Action Creates and throws Only declares possibility

Example Code with Both:
import java.io.*; // Custom Exception class InsufficientBalanceException extends Exception { InsufficientBalanceException(String message) { super(message); } } class BankAccount { private int balance; BankAccount(int initialBalance) { balance = initialBalance; } // 'throws' declares method may throw exception void withdraw(int amount) throws InsufficientBalanceException { System.out.println("Attempting to withdraw: " + amount); if (amount > balance) { // 'throw' actually throws the exception throw new InsufficientBalanceException( "Insufficient balance. Available: " + balance ); } balance -= amount; System.out.println("Withdrawal successful"); System.out.println("Remaining balance: " + balance); } // Method with multiple exception declarations void processTransaction() throws IOException, InsufficientBalanceException { // Can throw multiple types throw new IOException("Network error"); } int getBalance() { return balance; } } class Main { public static void main(String[] args) { BankAccount account = new BankAccount(1000); System.out.println("Initial balance: " + account.getBalance()); // Test 1: Valid withdrawal try { account.withdraw(500); } catch (InsufficientBalanceException e) { System.out.println("Error: " + e.getMessage()); } // Test 2: Invalid withdrawal (exceeds balance) try { account.withdraw(800); // Only 500 left } catch (InsufficientBalanceException e) { System.out.println("Error: " + e.getMessage()); } System.out.println("Final balance: " + account.getBalance()); } } Output: Initial balance: 1000 Attempting to withdraw: 500 Withdrawal successful Remaining balance: 500 Attempting to withdraw: 800 Error: Insufficient balance. Available: 500 Final balance: 500
Explanation:

1. throws keyword:
• Used in method signature: void withdraw(...) throws InsufficientBalanceException
• Declares that this method MAY throw an exception
• Informs the caller to handle the exception
• Can declare multiple exceptions: throws IOException, SQLException

2. throw keyword:
• Used inside method body: throw new InsufficientBalanceException(...)
• Actually creates and throws the exception object
• Execution stops at this point and jumps to catch block
• Can only throw one exception at a time

Real-world Analogy:
throws: Sign on door saying "Beware: Area may have obstacles"
throw: Actually placing an obstacle on the path

Key Point: throws is a warning/declaration, throw is the actual action of throwing an exception.