CodeWithSubhsam
🔹 1. Definition of Exception
An exception is an event that occurs during the execution of a program and disrupts the
normal flow of instructions.
🔹 2. Why Use Exception Handling?
🔸 Real-World Analogy:
Just like we prepare for unexpected situations (e.g., carrying a spare tire for a flat), in
programming, exception handling prepares for unexpected inputs, logic errors, or system
failures.
🔸 Main Purpose:
To gracefully handle errors instead of crashing the program.
To maintain normal flow of the application.
To separate error-handling code from regular logic.
🔹 3. Common Exception Scenarios
Scenario Example
Division by zero int a = 10 / 0;
File not found FileReader f = new FileReader("abc.txt");
Accessing null object String s = null; s.length();
Invalid array index int arr[] = new int[3]; arr[5];
⚖️ Difference between Exceptions and
Errors in Java
Aspect Exception Error
Problems that occur during program Serious issues that occur at runtime
Definition
execution and can be handled. and cannot be handled.
✅ Yes, mostly recoverable using try- ❌ No, not usually recoverable by
Recoverable?
catch. the program.
CodeWithSubhsam
Aspect Exception Error
Package java.lang.Exception java.lang.Error
OutOfMemoryError,
NullPointerException, IOException,
Examples StackOverflowError,
ArithmeticException
VirtualMachineError
Input errors, wrong logic, invalid data, Memory crash, system failure,
Use Case
etc. hardware issues, JVM crash
Can be handled with code (try-catch- Usually, cannot be handled or
Handling
finally) should not be handled
Type of Issue Programmer-level issues (bugs) System-level issues (JVM, memory)
🔹 Example of Exception:
try {
int a = 10 / 0; // ArithmeticException
} catch (ArithmeticException e) {
System.out.println("Cannot divide by zero.");
}
🔹 Example of Error:
public class Test {
public static void main(String[] args) {
main(args); // Recursive call leads to StackOverflowError
}
}
✅ Summary:
Exception = can be handled, program bug
Error = cannot be handled, system failure
📘 Types of Exceptions in Java
Java divides exceptions into:
CodeWithSubhsam
✅ 1. Inbuilt Exception (Predefined by Java)
🔸 Meaning:
Java already provides many ready-made exceptions to handle common errors.
📌 Examples:
ArithmeticException → when divide by zero
NullPointerException → when accessing null object
ArrayIndexOutOfBoundsException → invalid array index
IOException → file errors
SQLException → database errors
💻 Example:
public class Demo {
public static void main(String[] args) {
int a = 10 / 0; // ArithmeticException (inbuilt)
}
}
INBUILT EXCEPTION FURTHER DEVIDED INTO TO PART
( | ) Checked Exceptions (Compile-Time)
Java forces you to handle these using try-catch or throws.
They occur due to external problems like file not found or database error.
Compiler checks them, so you must handle them.
( || ) Unchecked Exceptions (Runtime)
Java does not force you to handle these.
These happen because of programming mistakes.
JVM checks at runtime, not compiler.
CodeWithSubhsam
✅ 2. User-Defined Exception (Custom Exception)
🔸 Meaning:
You create your own exception class based on specific needs using extends Exception or
extends RuntimeException.
📌 Why use?
When you want to throw an error for your own rules (e.g., age < 18, invalid input).
💻 Example:
class MyException extends Exception {
MyException(String msg) {
super(msg);
}
}
public class Test {
public static void main(String[] args) throws MyException {
int age = 16;
if (age < 18) {
throw new MyException("Age must be 18 or above.");
} else {
System.out.println("Eligible");
}
}
CodeWithSubhsam
( || ) Unchecked Exceptions (Runtime)
✅ 1. ArithmeticException
Occurs when dividing by zero.
public class Example {
public static void main(String[] args) {
int a = 10 / 0; // ArithmeticException
}
}
✅ 2. ClassCastException
Occurs when trying to cast an object to an incompatible class.
public class Example {
public static void main(String[] args) {
Object obj = new String("Java");
Integer num = (Integer) obj; // ClassCastException
}
CodeWithSubhsam
✅ 3. NullPointerException
Occurs when accessing a method or variable on a null object.
public class Example {
public static void main(String[] args) {
String str = null;
System.out.println(str.length()); // NullPointerException
}
}
✅ 4. ArrayIndexOutOfBoundsException
Occurs when accessing an invalid array index.
public class Example {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
System.out.println(arr[5]); // ArrayIndexOutOfBoundsException
}
}
✅ 5. ArrayStoreException
Occurs when storing the wrong data type in an array.
public class Example {
public static void main(String[] args) {
Object[] arr = new String[3];
arr[0] = 100; // ArrayStoreException
}
}
6. StringIndexOutOfBoundsException in Java
Occurs when you try to access a character at an invalid index in a string.
CodeWithSubhsam
🔸 Example Code:
public class Example {
public static void main(String[] args) {
String str = "Java";
char ch = str.charAt(10); // StringIndexOutOfBoundsException
}
}
( | ) Checked Exceptions (Compile-Time)
✅ 1. IOException
Occurs during input/output operations.
import java.io.*;
public class Example {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("file.txt"); // File might not exist
}
}
✅ 2. FileNotFoundException
A subclass of IOException.
import java.io.*;
public class Example {
public static void main(String[] args) throws FileNotFoundException {
FileInputStream fis = new FileInputStream("abc.txt"); // File not found
}
}
CodeWithSubhsam
✅ 3. ClassNotFoundException
Occurs when a class is not found at runtime.
public class Example {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.abc.MyClass"); // Class doesn't exist
}
}
🔄 Control Flow in Exception Handling
📘 Definition:
Control flow refers to how Java executes code when an exception occurs in a try-catch-
finally block.
✅ 1. Normal Flow (No Exception)
public class Test {
public static void main(String[] args) {
try {
System.out.println("1. Inside try");
} catch (Exception e) {
System.out.println("2. Inside catch");
} finally {
System.out.println("3. Inside finally");
}
System.out.println("4. After try-catch-finally");
}
}
CodeWithSubhsam
🧾 Output:
1. Inside try
3. Inside finally
4. After try-catch-finally
✅ JVM Reaction to Exceptions in Java
🔸 1. If Exception is Caught (Handled):
JVM continues program execution smoothly.
No program termination.
Example:
public class Example {
public static void main(String[] args) {
try {
int a = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Exception handled: " + e);
}
System.out.println("Program continues...");
}
}
🟢 Output:
Exception handled: java.lang.ArithmeticException: / by zero
Program continues...
🔸 2. If Exception is Not Caught (Unhandled):
JVM stops program execution.
JVM prints:
o Name of Exception
o Description
CodeWithSubhsam
o Stack trace
Example:
public class Example {
public static void main(String[] args) {
int a = 10 / 0; // Unhandled
}
}
🔴 Output:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Example.main(Example.java:3)
✅ Use of try, catch, and finally in Java
🔹 1. try block
Used to enclose code that may throw an exception.
try {
int a = 10 / 0;
}
🔹 2. catch block
Handles the exception thrown in the try block.
catch (ArithmeticException e) {
System.out.println("Cannot divide by zero!");
}
🔹 3. finally block
Always executes, whether an exception occurs or not. Used to close resources.
finally {
System.out.println("This block always executes.");
}
CodeWithSubhsam
✅ Full Example:
public class Example {
public static void main(String[] args) {
try {
int a = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Exception caught.");
} finally {
System.out.println("Finally block executed.");
}
}
}
🟢 Output:
Exception caught.
Finally block executed.
✅ THROW AND THROWS KEYWORD IN JAVA
CodeWithSubhsam
THROW CODE
public class Main {
public static void main(String[] args) {
try{
int a =10;
System.out.println(10/a);
if(a==10){
throw new ArithmeticException("This is an Exception Occur");
}
}catch (ArithmeticException e){
System.out.println("An Exception Occur "+e.getMessage());
}
}
}
THROWS CODE
public class Main {
public static void main(String[] args) {
try{
run();
}catch (ArithmeticException e){
System.out.println(e.getMessage());
}
}
public static void run() throws ArithmeticException {
CodeWithSubhsam
System.out.println(10 / 0);
}
}
📘 : Byte Streams and Character Streams
🔶 What is a Stream in Java?
A stream is a flow of data between a source and destination. Java uses streams to perform
input (read) and output (write) operations on files, networks, memory, etc.
Streams are of two types:
1. Byte Streams
2. Character Streams
✅ 1. Byte Streams
🔸 Definition:
Byte Streams are used to perform input and output of 8-bit bytes. These are suitable for
handling all types of binary files such as images, audio, video, PDF, etc.
🔸 Key Features:
Deals with raw binary data
Reads/writes one byte at a time
Not character-encoding aware
Useful for non-text files
🔸 Important Classes:
InputStream (abstract) → Base class for reading bytes
o Example: FileInputStream, BufferedInputStream, ByteArrayInputStream
OutputStream (abstract) → Base class for writing bytes
o Example: FileOutputStream, BufferedOutputStream, DataOutputStream
CodeWithSubhsam
import java.io.*;
class Demo {
public static void main(String[] args) throws Exception {
FileInputStream f = new FileInputStream("a.txt");
System.out.print((char) f.read());
f.close();
}
}
✅ 2. Character Streams
🔸 Definition:
Character Streams are used to perform input and output of 16-bit Unicode characters.
They are ideal for handling text files.
🔸 Key Features:
Deals with characters
Uses character encoding
Reads/writes character by character
Automatically handles encoding like UTF-8 or UTF-16
🔸 Important Classes:
Reader (abstract) → Base class for reading characters
o Example: FileReader, BufferedReader, CharArrayReader
Writer (abstract) → Base class for writing characters
o Example: FileWriter, BufferedWriter, PrintWriter
🔸 Advantages:
Best for reading and writing text-based data
Supports Unicode and multi-language character sets
CodeWithSubhsam
import java.io.*;
class Demo {
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader("a.txt");
System.out.print((char) fr.read());
fr.close();
}
}
What is Multithreading?
🟦 Multithreading is a process to execute multiple threads at the same time without
dependency of other threads called multithreading.
What is a thread?
🟦 Thread is a pre-defined class which is available in java.lang package.
🟦 Thread is a basic unit of CPU and it is well known for independent execution.
Method 1: Using Thread Class
Java provides Thread Class to achieve programming invoking threads thereby some major
methods of thread class are shown below in the tabular format with which we deal frequently
along the action performed by them.
Methods Action Performed
It checks whether the current thread is daemon or not
isDaemon() checks if a thread is running in the background or not.
isDaemon()
If it's running in background → returns true
If it's a normal thread (main work) → returns false
start() It starts the execution of the thread
CodeWithSubhsam
Methods Action Performed
It does the executable operations statements in the body of this method
run()
over a thread
It is a static method that puts the thread to sleep for a certain time been
sleep()
passed as an argument to it
wait() It sets the thread back in waiting state.
notify() It gives out a notification to one thread that is in waiting state
notifyAll() It gives out a notification to all the thread in the waiting state
setDaemon() It set the current thread as Daemon thread
stop() It is used to stop the execution of the thread
resume() It is used to resume the suspended thread.
How to create Thread in Java?
🔴 1. By extending Thread class
🔴 2. By implementing Runnable interface.
class A
class B extends A {
independent task1; // 10s
independent task2; // 5s
}
By Thread class
CodeWithSubhsam
public class ThreadedProgram extends Thread {
@Override
public void run() {
String threadName = Thread.currentThread().getName();
for (int i = 0; i < 3; i++) {
System.out.println("Run method: " + threadName);
}
}
public static void main(String[] args) {
ThreadedProgram t1 = new ThreadedProgram(); // create thread 1
ThreadedProgram t2 = new ThreadedProgram(); // create thread 2
t1.setName("Thread-1");
t2.setName("Thread-2");
t1.start(); // start thread 1
t2.start(); // start thread 2
}
✅ By Runnable Interface
public class ThreadedProgram implements Runnable {
@Override
public void run() {
String threadName = Thread.currentThread().getName();
for (int i = 0; i < 3; i++) {
System.out.println("Run method: " + threadName);
}
CodeWithSubhsam
public static void main(String[] args) {
ThreadedProgram task = new ThreadedProgram();
Thread thread1 = new Thread(task, "Thread-1");
Thread thread2 = new Thread(task, "Thread-2");
thread1.start();
thread2.start();
}
}
🔄 Thread Life Cycle (with Explanation)
The Java thread goes through these 5 main states:
1️⃣ New
Thread is created, but not started yet.
Code:
Thread t = new Thread();
CodeWithSubhsam
2️⃣ Runnable
You called start(). Thread is ready to run.
It’s in the thread pool, waiting for CPU.
Code:
t.start(); // moves to Runnable
3️⃣ Running
Thread has got CPU time and is now running its run() method.
It stays here until:
o It finishes (run() ends)
o It sleeps
o It waits or yields
4️⃣ Blocked / Waiting / Sleeping (Red state)
🔴 These are paused states:
Cause Method
Sleep Thread.sleep(ms)
Waiting for lock wait()
Manual pause suspend() (Deprecated)
➡️ To return to Runnable:
Sleep time finishes
notify() / notifyAll() called
resume() (if suspended)
5️⃣ Dead
Thread has finished execution or stopped manually.
Code:
return; // or run() method ends
CodeWithSubhsam
🧠 Summary Table:
State Meaning
New Thread is created
Ready to run (after
Runnable
start())
Running Actually executing
Waiting Temporarily paused
Dead Execution finished
Priorities in Thread
Priority of thread is a concept where each thread is having a priority which is represented
by numbers ranging from 1 to 10.
The default priority is set to 5 as excepted.
Minimum priority is set to 1.
Maximum priority is set to 10.
Here 3 constants are defined in it namely as follows:
1. public static int NORM_PRIORITY
2. public static int MIN_PRIORITY
3. public static int MAX_PRIORITY
We will use currentThread() method to get the name of the current thread. User can
also use setName() method if he/she wants to make names of thread as per choice
for understanding purposes.
getName() method will be used to get the name of the thread.
class MyThread extends Thread {
public void run() {
System.out.println(Thread.currentThread().getName() + " is running with priority " +
getPriority());
}
}
CodeWithSubhsam
public class TestPriority {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.setName("Thread-1");
t2.setName("Thread-2");
t1.setPriority(Thread.MIN_PRIORITY); // 1
t2.setPriority(Thread.MAX_PRIORITY); // 10
t1.start();
t2.start();
}
}
OUT Put -
Thread-1 is running with priority 1
Thread-2 is running with priority 10
⚠️ Note:
Setting priority is just a hint to the JVM, not a guarantee.
The OS may ignore it, especially in modern systems.
Synchronization
It is the mechanism that bounds the access of multiple threads to share a common resource
hence is suggested to be useful where only one thread at a time is granted the access to run
over.
It is implemented in the program by using 'synchronized' keyword.
Why Synchronization is Required?
1. Data inconsistency issues are the primary issue where multiple threads are
accessing the common memory which sometimes results in faults in order to avoid
that a thread is overlooked by another thread if it fails out.
2. Data integrity
CodeWithSubhsam
3. To work with a common shared resource which is very essential in the real world
such as in banking systems.
📘 Inter-thread Communication in Java
Inter-thread communication means threads talking to each other — mainly used to
coordinate their actions (like wait for something or notify others).
🧠 Why needed?
If one thread is producing data and another is consuming, they must communicate to
avoid issues like:
Consuming before producing
Producing too much before consumption
✅ Key Methods (in Object class):
1. wait()
→ Thread pauses and releases the lock until notified.
2. notify()
→ Wakes up one waiting thread.
3. notifyAll()
→ Wakes up all waiting threads.
🔒 Must be used inside a synchronized block.
🚦 Real-life example:
👩🍳 Cook (producer) prepares food → 💤 Waiter waits (wait()) → 🍽️ Cook says
“ready!” (notify()) → Waiter serves