Exception Handling Fundamentals
What is an Exception?
An exception is an abnormal condition that arises during the execution of a program. It disrupts
the normal flow of program instructions. When an exceptional condition occurs, an object
representing that condition is created and thrown in the method that caused the error.
Why Exception Handling?
Without proper exception handling:
Programs crash unexpectedly
Users see cryptic error messages
Resources may not be properly released
Debugging becomes difficult
With exception handling:
Programs can recover gracefully from errors
Meaningful error messages can be displayed
Resources are properly cleaned up
Code becomes more robust and maintainable
The java's exception handling is built upon five keywords:
Keywor
Purpose
d
try Encloses code that might throw an exception
catch Handles the exception
throw Manually throws an exception
throws Declares exceptions a method might throw
finally Code that always executes
Basic Structure
java
try
{
// Code that might throw an exception
}
catch (ExceptionType e)
{
// Handle the exception
}
finally
{
// Cleanup code (always executes)
}
2. Exception Types
Exception Hierarchy
All exception types are subclasses of the built-in class Throwable. The hierarchy is:
Checked vs Unchecked Exceptions
Checked Exceptions:
Must be either caught or declared in the method signature using throws
Compiler enforces handling
Examples: IOException, SQLException, FileNotFoundException
Unchecked Exceptions (Runtime Exceptions):
Do not require explicit handling
Extend RuntimeException
Usually indicate programming bugs
Examples: NullPointerException, ArithmeticException,
ArrayIndexOutOfBoundsException
Common Built-in Exceptions
public class CommonExceptions {
public static void main(String[] args)
// 1. ArithmeticException - Division by zero
// int result = 10 / 0;
// 2. NullPointerException - Accessing null reference
// String str = null;
// int len = [Link]();
// 3. ArrayIndexOutOfBoundsException - Invalid array index
// int[] arr = {1, 2, 3};
// int val = arr[5];
// 4. NumberFormatException - Invalid number format
// int num = [Link]("abc");
// 5. StringIndexOutOfBoundsException - Invalid string index
// String s = "Hello";
// char c = [Link](10);
}
}
3. Uncaught Exceptions
When an exception is not caught, the Java runtime system handles it using its default exception
handler. This handler:
1. Prints a description of the exception
2. Prints the stack trace (method call hierarchy)
3. Terminates the program
Example: Uncaught Exception
public class UncaughtExceptionDemo {
public static void main(String[] args) {
int numerator = 10;
int denominator = 0;
// This will cause ArithmeticException
int result = numerator / denominator;
// This line never executes
[Link]("Result: " + result);
}
}
Output:
Exception in thread "main" [Link]: / by zero at
[Link]([Link])
Understanding the Stack Trace
The stack trace shows:
Exception type: [Link]
Exception message: / by zero
Location: Class name, method name, file name, line number
4. Using try and catch
The try-catch block allows you to handle exceptions gracefully.
Basic Syntax
java
try { // Code that might throw an exception} catch (ExceptionType
exceptionObject) { // Exception handling code}
Example: Division by Zero
java
public class TryCatchDemo
{
public static void main(String[] args)
{ int numerator = 10;
int denominator = 0;
try {
int result = numerator / denominator;
[Link]("Result: " + result);
}
catch (ArithmeticException e)
{
[Link]("Error: Cannot divide by zero!"); [Link]("Exception
message: " + [Link]());
}
[Link]("Program continues after exception handling...");
}
}
Output:
Error: Cannot divide by zero!Exception message: / by zeroProgram
continues after exception handling...
Example: Array Index Out of Bounds
java
public class ArrayExceptionDemo
{
public static void main(String[] args)
{
int[] numbers = {10, 20, 30, 40, 50};
Try
{
[Link]("Accessing element at index 2: " +
numbers[2]);
[Link]("Accessing element at index 10: " +
numbers[10]);
}
catch (ArrayIndexOutOfBoundsException e)
{
[Link]("Error: Invalid array index!");
[Link]("Array length is: " + [Link]);
}
}
}
Output:
Accessing element at index 2: 30Error: Invalid array index!Array length is:
5
Important Methods of Exception Class
Method Description
Returns the description of the
getMessage()
exception
Returns exception name and
toString()
description
printStackTrace(
Prints the stack trace
)
getCause() Returns the cause of the exception
java
public class ExceptionMethodsDemo
{
public static void main(String[] args)
{
Try
{
int result = 10 / 0;
}
catch (ArithmeticException e)
{
[Link]("getMessage(): " + [Link]());
[Link]("toString(): " + [Link]());
[Link]("\nStack Trace:"); [Link]();
}
}
}
5. Multiple catch Clauses
When multiple types of exceptions can occur in a single try block, you can use multiple catch
clauses.
Syntax
java
try { // Code that might throw different exceptions} catch
(ExceptionType1 e1) { // Handle ExceptionType1} catch
(ExceptionType2 e2) { // Handle ExceptionType2} catch
(ExceptionType3 e3) { // Handle ExceptionType3}
Rules for Multiple catch Clauses
1. Order matters: More specific exceptions must come before more general ones
2. Only one catch block executes for a given exception
3. Superclass exceptions should be caught after subclass exceptions
Example: Multiple catch Blocks
java
public class MultipleCatchDemo
{
public static void main(String[] args)
{
int[] numbers = {10, 20, 0, 40};
try
{
// This might cause ArrayIndexOutOfBoundsException
int value = numbers[2];
// This might cause ArithmeticException
int result = 100 / value;
[Link]("Result: " + result);
}
catch (ArrayIndexOutOfBoundsException e)
{
[Link]("Array index error: " + [Link]());
}
catch (ArithmeticException e)
{
[Link]("Arithmetic error: " + [Link]());
}
catch (Exception e)
{
// General catch block - catches any other exception
[Link]("Some other error occurred: " + [Link]());
}
[Link]("Program continues...");
}
}Output:
Arithmetic error: / by zeroProgram continues...
Multi-catch Block
You can catch multiple exception types in a single catch block:
java
try { // Code} catch (ArithmeticException |
ArrayIndexOutOfBoundsException e) { [Link]("Error: " +
[Link]());}
Incorrect Order Example (Compile Error)
java
// This will NOT compile!try { int result = 10 / 0;} catch (Exception e)
{ // General exception first - ERROR! [Link]("Exception");}
catch (ArithmeticException e) { // More specific - unreachable
[Link]("ArithmeticException");}
6. Nested try Statements
A try block can be placed inside another try block, creating nested exception handling.
Why Use Nested try?
Different parts of code may require different exception handling
Inner exceptions can be handled locally while outer exceptions are handled globally
Provides more fine-grained control over exception handling
Syntax
java
try { // Outer try block try { // Inner try block } catch
(ExceptionType1 e) { // Handle inner exception }} catch
(ExceptionType2 e) { // Handle outer exception}
Example: Nested try Blocks
java
public class NestedTryDemo {
public static void main(String[] args) {
int[] numbers = {10, 5, 0};
try {
[Link]("Outer try block started");
for (int i = 0; i < 4; i++) {
try {
[Link]("\nInner try - Iteration " + i);
int value = numbers[i];
int result = 100 / value;
[Link]("100 / " + value + " = " + result);
} catch (ArithmeticException e) {
[Link]("Inner catch: Division by zero at index " + i);
}
}
} catch (ArrayIndexOutOfBoundsException e) {
[Link]("\nOuter catch: Array index out of bounds!");
}
[Link]("\nProgram completed.");
}
}
Output:
Outer try block started
Inner try - Iteration 0
100 / 10 = 10
Inner try - Iteration 1
100 / 5 = 20
Inner try - Iteration 2
Inner catch: Division by zero at index 2
Inner try - Iteration 3
Outer catch: Array index out of bounds!
Program [Link] Propagation in Nested try
If an exception is not caught by an inner catch, it propagates to the
outer try-catch block.
public class ExceptionPropagation {
public static void main(String[] args) {
try {
try {
int[] arr = new int[3];
arr[5] = 10; // ArrayIndexOutOfBoundsException
} catch (ArithmeticException e) {
// This won't catch ArrayIndexOutOfBoundsException
[Link]("Inner catch: " + e);
}
} catch (ArrayIndexOutOfBoundsException e) {
// Exception propagates here
[Link]("Outer catch: Array index error!");
}
}
}
7. The throw Keyword
The throw keyword is used to explicitly throw an exception from your code.
Syntax
java
throw exceptionObject;
Creating and Throwing Exceptions
java
throw new ExceptionType("Error message");
Example: Basic throw Usage
java
public class ThrowDemo { public static void main(String[] args)
{ try { validateAge(15); } catch (IllegalArgumentException
e) { [Link]("Exception caught: " + [Link]());
} } static void validateAge(int age) { if (age < 18)
{ throw new IllegalArgumentException("Age must be 18 or above");
} [Link]("Age is valid: " + age); }}
Output:
Exception caught: Age must be 18 or above
Example: Throwing Exception for Invalid Input
java
public class BankAccount { private double balance; public
BankAccount(double initialBalance) { if (initialBalance < 0)
{ throw new IllegalArgumentException("Initial balance cannot be
negative"); } [Link] = initialBalance; } public void
withdraw(double amount) { if (amount <= 0) { throw new
IllegalArgumentException("Withdrawal amount must be positive"); }
if (amount > balance) { throw new
IllegalArgumentException("Insufficient funds"); } balance -=
amount; [Link]("Withdrawn: " + amount + ", New
Balance: " + balance); } public static void main(String[] args)
{ try { BankAccount account = new BankAccount(1000);
[Link](500); [Link](600); // This will throw
exception } catch (IllegalArgumentException e)
{ [Link]("Error: " + [Link]()); } }}
8. The throws Keyword
The throws keyword is used in method declarations to indicate that the method might throw
certain exceptions.
Difference Between throw and throws
throw throws
Used to explicitly throw an exception Used to declare exceptions
Followed by exception class
Followed by an exception instance
names
Used inside a method body Used in method signature
Can throw only one exception at a
Can declare multiple exceptions
time
Syntax
java
returnType methodName(parameters) throws Exception1, Exception2
{ // Method body}
Example: Using throws
java
import [Link].*;public class ThrowsDemo { // Method declares that it
throws IOException public static void readFile(String filename) throws
IOException { FileReader file = new FileReader(filename);
BufferedReader reader = new BufferedReader(file); String line =
[Link](); [Link]("First line: " + line);
[Link](); } public static void main(String[] args) { try {
readFile("[Link]"); } catch (IOException e)
{ [Link]("File error: " + [Link]()); } }}
Example: Combining throw and throws
java
public class ValidateAge { // Method uses both throw and throws
public static void checkAge(int age) throws IllegalArgumentException {
if (age < 0) { throw new IllegalArgumentException("Age cannot be
negative"); } if (age < 18) { throw new
IllegalArgumentException("Must be 18 or older"); }
[Link]("Valid age: " + age); } public static void
main(String[] args) { try { checkAge(25); // Valid
checkAge(15); // Invalid - throws exception } catch
(IllegalArgumentException e) { [Link]("Validation
failed: " + [Link]()); } }}
9. The finally Block
The finally block contains code that always executes, regardless of whether an exception
occurs or not.
Purpose of finally
Cleanup operations (closing files, database connections, releasing resources)
Code that must execute regardless of success or failure
Ensuring critical operations are completed
Syntax
java
try { // Code that might throw exception} catch (ExceptionType e) { //
Handle exception} finally { // Always executes}
Example: finally Always Executes
java
public class FinallyDemo { public static void main(String[] args) {
// Case 1: No exception [Link]("=== Case 1: No
Exception ==="); try { int result = 10 / 2;
[Link]("Result: " + result); } catch (ArithmeticException
e) { [Link]("Exception caught"); } finally
{ [Link]("Finally block executed"); }
[Link](); // Case 2: Exception occurs
[Link]("=== Case 2: Exception Occurs ==="); try {
int result = 10 / 0; [Link]("Result: " + result); }
catch (ArithmeticException e) { [Link]("Exception
caught: " + [Link]()); } finally
{ [Link]("Finally block executed"); } }}
Output:
=== Case 1: No Exception ===Result: 5Finally block executed=== Case
2: Exception Occurs ===Exception caught: / by zeroFinally block
executed
Example: Resource Cleanup
import [Link].*;
public class ResourceCleanup {
public static void main(String[] args) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("[Link]"));
String line = [Link]();
[Link]("Content: " + line);
} catch (FileNotFoundException e) {
[Link]("File not found: " + [Link]());
} catch (IOException e) {
[Link]("Error reading file: " + [Link]());
} finally {
// Always close the reader
try {
if (reader != null) {
[Link]();
[Link]("Reader closed successfully");
}
} catch (IOException e) {
[Link]("Error closing reader");
}
}
}
}
try-with-resources (Java 7+)
A cleaner way to handle resources that implements AutoCloseable:
java
import [Link].*; // Line 1: Imports all classes from the [Link] package
public class TryWithResources { // Line 2: Defines the class TryWithResources
public static void main(String[] args) { // Line 3: Main method begins
// Resource is automatically closed // Line 4: Comment explaining automatic resource management
try (BufferedReader reader = // Line 5: Begins try-with-resources statement
new BufferedReader(
new FileReader("[Link]"))) {
// Creates a BufferedReader object to read from "[Link]"
// The reader is automatically closed after the try block ends
String line = [Link](); // Line 6: Reads one line from the file and stores it in 'line'
[Link]("Content: " + line);
// Line 7: Prints the contents read from the file
} // Line 8: Ends the try block and automatically closes the reader
catch (IOException e) { // Line 9: Catches any input/output exceptions
[Link]("Error: " +
[Link]()); // Line 10: Prints the exception message
} // Line 11: Ends the catch block
// No need for finally - resource auto-closed
// Line 12: Comment explaining that finally is unnecessary
} // Line 13: Ends the main() method
} // Line 14: Ends the TryWithResources class10. Creating Your Own Exception Subclasses
You can create custom exceptions by extending the Exception class (for checked exceptions)
or RuntimeException class (for unchecked exceptions).
Basic Custom Exception
java
// Custom checked exceptionclass CustomException extends Exception
{ public CustomException(String message) { super(message); }}//
Custom unchecked exceptionclass CustomRuntimeException extends
RuntimeException { public CustomRuntimeException(String message) {
super(message); }}
Example: WeakPasswordException
java
// Custom exception for weak passwordsclass WeakPasswordException
extends Exception { private String password; public
WeakPasswordException(String message, String password)
{ super(message); [Link] = password; } public
String getPassword() { return password; }}// Password validation
systempublic class PasswordValidator { public static void
validatePassword(String password) throws WeakPasswordException {
if (password == null || [Link]() < 8) { throw new
WeakPasswordException( "Password must be at least 8
characters long", password ); }
[Link]("Password is strong!"); } public static void
main(String[] args) { String[] passwords = {"abc", "12345678",
"pass", "securePass123"}; for (String pwd : passwords)
{ try { [Link]("\nValidating: " + pwd);
validatePassword(pwd); } catch (WeakPasswordException e) {
[Link]("Weak password detected: " + [Link]());
[Link]("Password length: " + [Link]().length());
} } }}
Example: CreditLimitExceededException
java
// Custom exception for credit limitclass CreditLimitExceededException
extends Exception { private int requestedCredits; private int
maxCredits; public CreditLimitExceededException(int requested, int
max) { super("Credit limit exceeded! Requested: " + requested + ",
Maximum allowed: " + max); [Link] = requested;
[Link] = max; } public int getExcessCredits() { return
requestedCredits - maxCredits; }}// College management systempublic
class CollegeManagement { private static final int MAX_CREDITS = 30;
public static void registerCourses(String studentName, int credits)
throws CreditLimitExceededException { if (credits >
MAX_CREDITS) { throw new
CreditLimitExceededException(credits, MAX_CREDITS); }
[Link](studentName + " successfully registered for " + credits
+ " credits"); } public static void main(String[] args) { try {
registerCourses("Alice", 25); // Success registerCourses("Bob", 35);
// Exceeds limit } catch (CreditLimitExceededException e)
{ [Link]("Registration failed: " + [Link]());
[Link]("Excess credits: " + [Link]()); } }}
Example: InsufficientFundsException
java
// Custom exception for insufficient fundsclass InsufficientFundsException
extends Exception { private double amount; public
InsufficientFundsException(String message, double amount)
{ super(message); [Link] = amount; } public double
getAmount() { return amount; }}// Online payment systempublic
class PaymentSystem { private double balance = 1000.0; public void
processTransaction(double amount) throws InsufficientFundsException {
if (amount <= 0) { throw new InsufficientFundsException(
"Transaction amount must be positive", amount ); } if
(amount > balance) { throw new InsufficientFundsException(
"Insufficient balance. Available: $" + balance, amount ); }
balance -= amount; [Link]("Transaction successful!
Amount: $" + amount); [Link]("Remaining balance: $" +
balance); } public static void main(String[] args)
{ PaymentSystem payment = new PaymentSystem(); try {
[Link](500); // Success
[Link](600); // Fails - insufficient funds } catch
(InsufficientFundsException e) { [Link]("Transaction
failed: " + [Link]()); } }}
Example: StockUnavailableException
java
// Custom exception for inventory managementclass
StockUnavailableException extends Exception { private int requested;
private int available; public StockUnavailableException(int requested,
int available) { super("Requested: " + requested + ", Available: " +
available); [Link] = requested; [Link] = available;
} public int getShortage() { return requested - available; }}//
Warehouse inventory systempublic class WarehouseInventory { public
static void withdrawStock(int available, int request) throws
StockUnavailableException { if (request > available)
{ throw new StockUnavailableException(request, available); }
int remaining = available - request; [Link]("Stock
withdrawn: " + request); [Link]("Remaining stock: " +
remaining); } public static void main(String[] args) { try {
[Link]("=== First Withdrawal ===");
withdrawStock(100, 50); // Success [Link]("\
n=== Second Withdrawal ==="); withdrawStock(30, 50); // Fails
} catch (StockUnavailableException e) { [Link]("Stock
withdrawal failed: " + [Link]());
[Link]("Shortage: " + [Link]() + " units"); } }}
Chained Exceptions
Chained exceptions allow you to associate one exception with another, preserving the original
cause of an error.
Chained exception in Java = When one exception causes another exception. You "wrap" the
original exception inside a new one so you don’t lose the root cause.
It’s basically: "This error happened because of that earlier error."
Why it exists
Without chaining, if you catch an exception and throw a new one, you lose the original stack
trace. Chaining keeps the full story.
Why Use Chained Exceptions?
Preserve the root cause of an exception
Provide more context about what went wrong
Enable better debugging and error tracking
How to do it
1. Using constructors — Most exception classes have a constructor that takes Throwable cause
try {
// something that throws SQLException
} catch (SQLException e) {
throw new ServiceException("Failed to update user", e); // e is chained
}
2. Using initCause() — If the exception doesn’t support it in
constructor
try {
// code
} catch (IOException e) {
ServiceException se = new ServiceException("File processing failed");
[Link](e); // chain it
throw se;
}
How to read the stack trace
ServiceException: Failed to update user
at [Link]([Link])
Caused by: [Link]: Connection timeout
at [Link]([Link])
...
Key methods from Throwable
Method What it does
getCause() Returns the exception that caused this one,
or null
initCause(Throwable) Sets the cause. Can only call once
printStackTrace() Prints both exceptions with Caused by
Custom exception with chaining
public class ServiceException extends Exception {
public ServiceException(String message, Throwable cause) {
super(message, cause); // pass cause to parent
}
Example: Basic Exception Chaining
public class ChainedExceptionDemo
{
public static void main(String[] args)
{
try
{
method1();
}
catch (Exception e)
{
[Link]("Caught: " + e);
[Link]("\n=== Exception Chain ===");
Throwable cause = [Link]();
while (cause != null)
{
[Link]("Caused by: " + cause);
cause = [Link]();
}
}
S.o.p(“the result is:”+result);
}
static void method1() throws Exception
{
try
{
method2();
}
catch (ArithmeticException e)
{
throw new Exception("Error in method1", e);
}
}
static void method2()
{
int result = 10 / 2;
}
}
Example: Railway Booking System
// Low-level exception
class NetworkDownException extends Exception
{
public NetworkDownException(String message)
{
super(message);
}
}
// High-level exception with chaining
class BookingFailException extends Exception
{
public BookingFailException(String message, Throwable cause)
{
super(message, cause);
}
}
// Railway booking system
public class RailwayBookingSystem
{
public static void connectToServer()
throws NetworkDownException
{
// Simulate network failure
throw new NetworkDownException(
"Server unreachable at [Link]"
);
}
public static void bookTicket(
String train,
String passenger
) throws BookingFailException
{
try
{
connectToServer();
// Booking logic would go here
}
catch (NetworkDownException e)
{
throw new BookingFailException(
"Failed to book ticket for "
+ passenger
+ " on "
+ train,
e
);
}
}
public static void main(String[] args)
{
try
{
bookTicket(
"Rajdhani Express",
"John Doe"
);
}
catch (BookingFailException e)
{
[Link](
"Booking Error: "
+ [Link]()
);
[Link](
"Root Cause: "
+ [Link]().getMessage()
);
[Link](
"\n=== Full Stack Trace ==="
);
[Link]();
}
}
}
Example : ATM
Example: Library Management System
// Line 1: Comment - Exception for stock issues
class OutOfStockException extends Exception { // Line 2: Defines a user-defined exception class
private String bookTitle; // Line 3: Stores the title of the unavailable book
public OutOfStockException(String bookTitle) { // Line 4: Constructor of OutOfStockException
super("Book out of stock: " + bookTitle); // Line 5: Calls Exception constructor and sets the message
[Link] = bookTitle; // Line 6: Stores the book title in instance variable
} // Line 7: Ends constructor
public String getBookTitle() { // Line 8: Getter method begins
return bookTitle; // Line 9: Returns the book title
} // Line 10: Ends getter method
} // Line 11: Ends OutOfStockException class
// Line 12: Comment - Exception for book issue failure
class BookIssueFailedException extends Exception { // Line 13: Defines another user-defined exception
public BookIssueFailedException(String message,
Throwable cause) { // Line 14: Constructor begins
super(message, cause); // Line 15: Stores message and original exception
} // Line 16: Ends constructor
} // Line 17: Ends BookIssueFailedException class
// Line 18: Comment - Library system
public class LibraryManagement { // Line 19: Main class begins
private static [Link]<String, Integer> inventory
= new [Link]<>(); // Line 20: Creates inventory HashMap
static { // Line 21: Static block begins
[Link]("Java Programming", 2); // Line 22: Adds Java Programming with 2 copies
[Link]("Data Structures", 0); // Line 23: Adds Data Structures with 0 copies
[Link]("Database Systems", 5); // Line 24: Adds Database Systems with 5 copies
} // Line 25: Ends static block
public static void checkAvailability(String bookTitle)
throws OutOfStockException { // Line 26: Method begins
Integer count = [Link](bookTitle); // Line 27: Gets available copies
if (count == null || count == 0) { // Line 28: Checks if book is unavailable
throw new OutOfStockException(bookTitle);// Line 29: Throws OutOfStockException
} // Line 30: Ends if block
} // Line 31: Ends checkAvailability()
public static void issueBook(String bookTitle,
String memberName)
throws BookIssueFailedException { // Line 32: Method begins
try { // Line 33: Try block begins
checkAvailability(bookTitle); // Line 34: Checks stock availability
int currentStock = [Link](bookTitle);
// Line 35: Gets current stock
[Link](bookTitle,
currentStock - 1); // Line 36: Decreases stock by 1
[Link]("Book '" + bookTitle +
"' issued to " +
memberName); // Line 37: Displays success message
} // Line 38: Ends try block
catch (OutOfStockException e) { // Line 39: Catch block begins
throw new BookIssueFailedException(
"Cannot issue book to " +
memberName, e); // Line 40: Throws chained exception
} // Line 41: Ends catch block
} // Line 42: Ends issueBook()
public static void main(String[] args) { // Line 43: Main method begins
String[] members = {"Alice", "Bob"}; // Line 44: Creates members array
String[] books = {"Java Programming",
"Data Structures"}; // Line 45: Creates books array
for (int i = 0; i < [Link]; i++) { // Line 46: For loop begins
try { // Line 47: Try block begins
issueBook(books[i], members[i]); // Line 48: Issues book to member
} // Line 49: Ends try block
catch (BookIssueFailedException e) { // Line 50: Catch block begins
[Link](
"\nIssue Failed: " +
[Link]()); // Line 51: Prints failure message
Throwable cause = [Link](); // Line 52: Gets root cause
if (cause instanceof OutOfStockException) {
// Line 53: Checks cause type
OutOfStockException stockError =
(OutOfStockException) cause;
// Line 54: Typecasts cause
[Link](
"Reason: " +
[Link]());
// Line 55: Prints original reason
} // Line 56: Ends if block
} // Line 57: Ends catch block
} // Line 58: Ends for loop
} // Line 59: Ends main method
} // Line 60: Ends LibraryManagement class
EXAMPLE : ATM
class CashDispenserJamException extends Exception
{
public CashDispenserJamException(String message)
{
super(message);
}
}
class CashWithdrawalFailedException extends Exception
{
public CashWithdrawalFailedException(String message,
Throwable cause)
{
super(message, cause);
}
}
public class ATMExceptionChainDemo
{
static void dispenseCash()
throws CashDispenserJamException
{
throw new CashDispenserJamException(
"Cash dispenser is jammed.");
}
static void withdrawCash()
throws CashWithdrawalFailedException
{
try
{
dispenseCash();
}
catch (CashDispenserJamException e)
{
throw new CashWithdrawalFailedException(
"Cash withdrawal failed. Please try again later.",
e);
}
}
public static void main(String[] args)
{
try
{
withdrawCash();
}
catch (CashWithdrawalFailedException e)
{
[Link]("Caught: " + e);
[Link]("Root Cause: " + [Link]());
}
}
}
12. The Java Thread Model
What is a Thread?
A thread is a lightweight sub-process, the smallest unit of processing. It is a separate path of
execution within a program.
Multithreading
Multithreading is the ability of a CPU to execute multiple threads concurrently. Java provides
built-in support for multithreaded programming.
Benefits of Multithreading
1. Improved performance: Better CPU utilization
2. Responsiveness: UI remains responsive while processing
3. Resource sharing: Threads share memory and resources
4. Simplified modeling: Natural way to model real-world scenarios
Thread States (Life Cycle)
Thread States
State Description
New Thread object created but not started
Runnable Thread is ready to run, waiting for CPU
Running Thread is currently executing
Blocked/ Thread is waiting for a resource or
Waiting condition
Terminated Thread has completed execution
13. The Main Thread
When a Java program starts, one thread begins running immediately - the main thread.
Characteristics of Main Thread
It is the thread from which other "child" threads are spawned
Often the last thread to finish execution
Performs various shutdown actions
Accessing the Main Thread
java
public class MainThreadDemo
{
public static void main(String[] args)
{ // Get reference to the main thread
Thread mainThread = [Link]();
[Link]("Current thread: " +
[Link]());
[Link]("Thread ID: " + [Link]());
[Link]("Thread Priority: " +
[Link]());
[Link]("Thread State: " + [Link]());
[Link]("Is Alive: " + [Link]()); //
Change thread name
[Link]("MyMainThread");
[Link]("\nAfter renaming: " +
[Link]()); }}
Output:
Current thread: mainThread
ID: 1
Thread Priority: 5
Thread State: RUNNABLE
Is Alive: true
After renaming: MyMainThread
EXAMPLE:
class MorningThread extends Thread
{
public void run()
{
for (int i = 1; i <= 3; i++)
{
[Link]("Good Morning");
}
}
}
class WelcomeThread extends Thread
{
public void run()
{
for (int i = 1; i <= 3; i++)
{
[Link]("Welcome to Java");
}
}
}
public class MultiThreadDemo
{
public static void main(String[] args)
{
MorningThread t1 = new MorningThread();
WelcomeThread t2 = new WelcomeThread();
[Link]();
[Link]();
}
}
Thread Priority
Thread priorities range from 1 (MIN_PRIORITY) to 10 (MAX_PRIORITY), with 5 being
NORM_PRIORITY.
java
public class ThreadPriorityDemo
{
public static void main(String[] args)
{
Thread t = [Link]();
[Link]("MIN_PRIORITY: " +
Thread.MIN_PRIORITY); // 1
[Link]("NORM_PRIORITY: " +
Thread.NORM_PRIORITY); // 5
[Link]("MAX_PRIORITY: " + Thread.MAX_PRIORITY);
// 10
[Link](Thread.MAX_PRIORITY);
[Link]("New Priority: " + [Link]());
}
}
14. Creating a Thread
There are two ways to create a thread in Java:
Method 1: Extending Thread Class
class MyThread extends Thread
{
@Override
public void run()
{
for (int i = 1; i <= 5; i++)
{
[Link](getName() + ": Count " + i);
try
{
[Link](500);
}
catch (InterruptedException e)
{
[Link]("Thread interrupted");
}
}
}
}
public class ExtendThreadDemo
{
public static void main(String[] args)
{
MyThread t1 = new MyThread();
[Link]("Thread-A");
[Link]();
[Link]("Main thread continues...");
}
}
Method 2: Implementing Runnable Interface
class MyRunnable implements Runnable
{
@Override
public void run()
{
for (int i = 1; i <= 5; i++)
{
[Link]([Link]().getName() + ":
Count " + i);
try
{
[Link](500);
}
catch (InterruptedException e)
{
[Link]("Thread interrupted");
}
}
}
}
public class RunnableDemo
{
public static void main(String[] args)
{
MyRunnable runnable = new MyRunnable();
Thread t1 = new Thread(runnable, "Thread-B");
[Link]();
[Link]("Main thread continues...");
}
}Using Lambda Expression (Java 8+)
java
public class LambdaThreadDemo { public static void main(String[] args)
{ Thread t1 = new Thread(() -> { for (int i = 1; i <= 5; i++) {
[Link]("Lambda Thread: " + i); } });
[Link](); }}
Comparison: Thread vs Runnable
Extending Thread Implementing Runnable
Cannot extend other classes Can extend other classes
Each thread creates unique Multiple threads can share same
object object
Simpler syntax More flexible design
15. Multiple Threads
class MorningThread extends Thread
{
public void run()
{
for (int i = 1; i <= 3; i++)
{
[Link]("Good Morning");
}
}
}
class WelcomeThread extends Thread
{
public void run()
{
for (int i = 1; i <= 3; i++)
{
[Link]("Welcome to Java");
}
}
}
public class MultiThreadDemo
{
public static void main(String[] args)
{
MorningThread t1 = new MorningThread();
WelcomeThread t2 = new WelcomeThread();
[Link]();
[Link]();
}
}
Example: Two Threads Printing Different Messages
class GreetingThread extends Thread
{
private String message;
private int count;
public GreetingThread(String name, String message, int count)
{
super(name);
[Link] = message;
[Link] = count;
}
@Override
public void run()
{
for (int i = 1; i <= count; i++)
{
[Link](getName() + ": " + message + " (Time "
+ i + ")");
try
{
[Link](300);
}
catch (InterruptedException e)
{
[Link](getName() + " interrupted");
}
}
}
}
public class MultipleThreadsDemo
{
public static void main(String[] args)
{
GreetingThread t1 = new GreetingThread(
"Morning-Thread",
"Good Morning",
3);
GreetingThread t2 = new GreetingThread(
"Welcome-Thread",
"Welcome to Java",
3);
[Link]();
[Link]();
[Link]("Both threads started!");
}
}
Example: Even and Odd Numbers
class EvenThread extends Thread
{
public EvenThread()
{
super("Even-Thread");
}
@Override
public void run()
{
[Link]("Even numbers from 1 to 10:");
for (int i = 2; i <= 10; i += 2)
{
[Link](getName() + ": " + i);
try
{
[Link](200);
}
catch (InterruptedException e)
{
[Link]("Interrupted");
}
}
}
}
class OddThread extends Thread
{
public OddThread()
{
super("Odd-Thread");
}
@Override
public void run()
{
[Link]("Odd numbers from 1 to 10:");
for (int i = 1; i <= 10; i += 2)
{
[Link](getName() + ": " + i);
try
{
[Link](200);
}
catch (InterruptedException e)
{
[Link]("Interrupted");
}
}
}
}
public class EvenOddDemo
{
public static void main(String[] args)
{
EvenThread evenThread = new EvenThread();
OddThread oddThread = new OddThread();
[Link]();
[Link]();
[Link]("Main thread finished starting child
threads");
}
}16. Using isAlive() and join()
isAlive() Method
Returns true if the thread is still running, false otherwise.
java
public final boolean isAlive()
join() Method
Causes the current thread to wait until the thread on which join() is called completes.
java
public final void join() throws InterruptedExceptionpublic final void
join(long milliseconds) throws InterruptedException
Example: Basic isAlive() and join()
java
class WorkerThread extends Thread { public WorkerThread(String
name) { super(name); } @Override public void run()
{ [Link](getName() + " started"); for (int i = 1; i <=
3; i++) { [Link](getName() + " working... step " + i);
try { [Link](500); } catch (InterruptedException e)
{ [Link](getName() + " interrupted"); } }
[Link](getName() + " completed"); }}public class JoinDemo
{ public static void main(String[] args) { WorkerThread t1 = new
WorkerThread("Thread-1"); WorkerThread t2 = new
WorkerThread("Thread-2"); [Link](); [Link](); //
Check if threads are alive [Link]("t1 is alive: " +
[Link]()); [Link]("t2 is alive: " +
[Link]()); // Wait for threads to complete try
{ [Link]("\nMain thread waiting for t1...");
[Link](); [Link]("t1 has finished");
[Link]("\nMain thread waiting for t2..."); [Link]();
[Link]("t2 has finished"); } catch
(InterruptedException e) { [Link]("Main thread
interrupted"); } // Check again [Link]("\
nAfter join:"); [Link]("t1 is alive: " + [Link]());
[Link]("t2 is alive: " + [Link]());
[Link]("\nMain thread completed"); }}
Example: ATM Withdrawal System
java
class ATMThread extends Thread { private static double balance =
10000.0; private double withdrawalAmount; private static Object lock
= new Object(); public ATMThread(String customerName, double
amount) { super(customerName); [Link] =
amount; } @Override public void run()
{ [Link](getName() + " requesting withdrawal of $" +
withdrawalAmount); synchronized (lock) { if
(withdrawalAmount <= balance) { [Link](getName()
+ " - Processing withdrawal..."); try
{ [Link](500); // Simulate processing time }
catch (InterruptedException e) { [Link](getName()
+ " interrupted"); } balance -=
withdrawalAmount; [Link](getName() + " -
Withdrawal successful. New balance: $" + balance); } else {
[Link](getName() + " - Insufficient funds. Available: $" +
balance); } } } public static double getBalance()
{ return balance; }}public class ATMDemo { public static void
main(String[] args) { ATMThread customer1 = new
ATMThread("Alice", 3000); ATMThread customer2 = new
ATMThread("Bob", 5000); ATMThread customer3 = new
ATMThread("Charlie", 4000); [Link]("Initial Balance:
$" + [Link]()); [Link]();
[Link](); [Link]();
[Link](); // Wait for all transactions to complete try
{ [Link](); [Link](); [Link]();
} catch (InterruptedException e) { [Link]("Main
interrupted"); } [Link]("\n=== Day's Closing
Balance: $" + [Link]() + " ==="); }}
Example: Weather Monitoring System
java
class SensorThread extends Thread { private String sensorType;
private int readings; public SensorThread(String sensorType, int
readings) { super(sensorType + "-Sensor"); [Link] =
sensorType; [Link] = readings; } @Override public void
run() { [Link](getName() + " started monitoring");
for (int i = 1; i <= readings; i++) { double value =
generateReading(); [Link]("%s Reading %d: %.2f%n",
sensorType, i, value); try { [Link]((long)
([Link]() * 1000) + 500); } catch (InterruptedException e) {
[Link](getName() + " interrupted"); } }
[Link](getName() + " finished monitoring"); } private
double generateReading() { switch (sensorType) { case
"Temperature": return 20 + [Link]() * 15; // 20-35°C
case "Humidity": return 40 + [Link]() * 40; // 40-80%
case "Pressure": return 1000 + [Link]() * 30; // 1000-1030
hPa default: return 0; } }}public class
WeatherMonitoringDemo { public static void main(String[] args)
{ SensorThread tempSensor = new SensorThread("Temperature", 3);
SensorThread humiditySensor = new SensorThread("Humidity", 3);
SensorThread pressureSensor = new SensorThread("Pressure", 3);
[Link]("=== Weather Monitoring System Started ===\n");
[Link](); [Link]();
[Link](); // Wait for all sensors to complete try
{ [Link](); [Link]("\nTemperature
sensor completed. isAlive: " + [Link]());
[Link](); [Link]("Humidity sensor
completed. isAlive: " + [Link]());
[Link](); [Link]("Pressure sensor
completed. isAlive: " + [Link]()); } catch
(InterruptedException e) { [Link]("Main thread
interrupted"); } [Link]("\n=== All Sensors
Finished Reporting ==="); }}
Example: Delivery Van Tracking System
java
class DeliveryVan extends Thread { private String vanId; public
DeliveryVan(String vanId) { super("Van-" + vanId); [Link] =
vanId; } @Override public void run() { String[] statuses =
{"Started", "En Route", "Delivered"}; for (String status :
statuses) { [Link](getName() + " Status: " + status);
try { // Different delays for different statuses int delay =
[Link]("En Route") ? 1500 : 800; [Link](delay);
} catch (InterruptedException e) { [Link](getName()
+ " delivery interrupted"); return; } } }}public class
DeliveryTrackingDemo { public static void main(String[] args)
{ DeliveryVan van1 = new DeliveryVan("001"); DeliveryVan van2
= new DeliveryVan("002"); DeliveryVan van3 = new
DeliveryVan("003"); [Link]("=== Logistics Tracking
System ===\n"); [Link]("Starting all delivery vans...\n");
[Link](); [Link](); [Link](); // Check status
while running [Link]("Van1 alive: " + [Link]());
[Link]("Van2 alive: " + [Link]());
[Link]("Van3 alive: " + [Link]());
[Link](); // Wait for all vans to complete try {
[Link](); [Link]("\n--- " + [Link]() + "
journey completed ---"); [Link]();
[Link]("--- " + [Link]() + " journey completed ---");
[Link](); [Link]("--- " + [Link]() + " journey
completed ---"); } catch (InterruptedException e)
{ [Link]("Tracking system interrupted"); }
[Link]("\n=== All Deliveries Completed ==="); }}
17. Practice Problems
Problem 1: Licence Exception
java
// Custom exception for driving licence validationclass LicenceException
extends Exception { private int age; public LicenceException(String
message, int age) { super(message); [Link] = age; }
public int getAge() { return age; }}public class
DrivingLicenceValidator { /** * Verifies if a person is eligible for
driving licence * * @param age The age of the applicant * @throws
LicenceException if age is below 18 * * The 'throws' keyword in the
method signature declares that * this method might throw a
LicenceException. This forces the * caller to either handle the exception
or declare it further. */ public static void verifyAge(int age) throws
LicenceException { if (age < 18) { // The 'throw' keyword is
used to explicitly throw an exception // Here we create a new
LicenceException object and throw it throw new LicenceException(
"Not eligible for driving licence. Minimum age is 18.",
age ); } [Link]("Eligible for driving licence!
Age: " + age); } public static void main(String[] args) { int[]
ages = {25, 16, 18, 14, 30}; for (int age : ages) { try {
[Link]("\nChecking age: " + age); verifyAge(age);
} catch (LicenceException e) { [Link]("Rejected: " +
[Link]()); [Link]("Applicant must wait " + (18
- [Link]()) + " more years"); } } }}
Problem 2: Hotel Room Booking
java
// Custom exception for excess room bookingclass
ExcessRoomBookingException extends Exception { private int
requested; private int maxAllowed; public
ExcessRoomBookingException(int requested, int maxAllowed)
{ super("Cannot book " + requested + " rooms. Maximum allowed: " +
maxAllowed); [Link] = requested; [Link] =
maxAllowed; } public int getExcessRooms() { return requested -
maxAllowed; }}public class HotelBookingSystem { private static final
int MAX_ROOMS_PER_BOOKING = 3; public static void
bookRooms(String guestName, int numRooms) throws
ExcessRoomBookingException { [Link]("\
nProcessing booking for: " + guestName);
[Link]("Requested rooms: " + numRooms); if
(numRooms > MAX_ROOMS_PER_BOOKING) { throw new
ExcessRoomBookingException(numRooms,
MAX_ROOMS_PER_BOOKING); }
[Link]("Booking confirmed! " + numRooms + " room(s)
reserved."); } public static void main(String[] args) { String[]
guests = {"Alice", "Bob", "Charlie"}; int[] rooms = {2, 5, 1};
for (int i = 0; i < [Link]; i++) { try
{ bookRooms(guests[i], rooms[i]); } catch
(ExcessRoomBookingException e) { [Link]("Booking
failed: " + [Link]()); [Link]("Please reduce
your booking by " + [Link]() + "
room(s)"); } } }}
Problem 3: Exam Portal Registration
java
// Custom exception for unregistered candidatesclass
UnregisteredCandidateException extends Exception { private String
candidateId; public UnregisteredCandidateException(String
candidateId) { super("Candidate " + candidateId + " is not
registered"); [Link] = candidateId; } public String
getCandidateId() { return candidateId; }}public class
OnlineExamPortal { private static [Link]<String>
registeredCandidates = new [Link]<>(); static { // Pre-
register some candidates [Link]("CAND001");
[Link]("CAND002");
[Link]("CAND003"); } public static void
registerCandidate(String candidateId, String name)
{ [Link](candidateId);
[Link]("Registration successful: " + name + " (" + candidateId
+ ")"); } public static void startExam(String candidateId) throws
UnregisteredCandidateException { [Link]("\nAttempting
to start exam for: " + candidateId); if (!
[Link](candidateId)) { throw new
UnregisteredCandidateException(candidateId); }
[Link]("Exam started successfully!");
[Link]("Good luck, candidate " + candidateId + "!"); }
public static void main(String[] args) { // Test cases String[]
candidates = {"CAND001", "CAND999", "CAND002", "CAND888"};
for (String candidateId : candidates) { try
{ startExam(candidateId); } catch
(UnregisteredCandidateException e)
{ [Link]("Access denied: " + [Link]());
[Link]("Please complete registration
first."); } } }}
Problem 4: Low Credit Score
java
// Custom exception for low credit scoreclass LowCreditScoreException
extends Exception { private int creditScore; private int
minimumRequired; public LowCreditScoreException(int creditScore,
int minimumRequired) { super("Credit score " + creditScore + " is
below minimum " + minimumRequired); [Link] =
creditScore; [Link] = minimumRequired; }
public int getPointsNeeded() { return minimumRequired - creditScore;
}}public class LoanEligibilityChecker { private static final int
MIN_CREDIT_SCORE = 700; public static void checkEligibility(String
customerName, int creditScore) throws LowCreditScoreException
{ [Link]("\n=== Loan Eligibility Check ===");
[Link]("Customer: " + customerName);
[Link]("Credit Score: " + creditScore); if
(creditScore < MIN_CREDIT_SCORE) { throw new
LowCreditScoreException(creditScore, MIN_CREDIT_SCORE); }
[Link]("✓ Eligible for loan!"); [Link]("You
may proceed with the application."); } public static void
main(String[] args) { String[] customers = {"Alice", "Bob", "Charlie"};
int[] scores = {750, 650, 720}; for (int i = 0; i <
[Link]; i++) { try
{ checkEligibility(customers[i], scores[i]); } catch
(LowCreditScoreException e) { [Link](" ✗ Not
eligible: " + [Link]()); [Link]("Need " +
[Link]() + " more points to qualify."); } } }}
Summary Table: Exception Handling
Keywords
Keywo
Purpose Example
rd
Enclose code that might throw
try try { riskyCode(); }
exception
catch Handle specific exception types catch (Exception e) { ... }
finally Execute cleanup code always finally { closeResources(); }
throw new
throw Explicitly throw an exception
Exception("Error");
Declare exceptions method might void method() throws
throws
throw Exception
Summary Table: Thread Methods
Method Description
start() Begins thread execution
run() Contains code to be executed
Pauses thread for specified
sleep(ms)
milliseconds
join() Waits for thread to complete
isAlive() Checks if thread is still running
getName() Returns thread name
setName() Sets thread name
getPriority() Returns thread priority
setPriority() Sets thread priority
currentThread
Returns reference to current thread
()