BCS-403 • OOP with Java Unit II Notes
Object Oriented
Programming with Java
BCS-403
Unit II Complete Notes
Exception Handling · I/O Basics · Multithreading
Bitwise Learning
Page 1
BCS-403 • OOP with Java Unit II Notes
Table of Contents
1 Exception Handling
1.1 The Idea Behind Exception
1.2 Exceptions & Errors / Types
1.3 Control Flow in Exceptions
1.4 Keywords: try · catch · finally · throw · throws
1.5 In-built Exceptions
1.6 User-Defined (Custom) Exceptions
2 Input / Output Basics
2.1 Streams – Byte & Character
2.2 Reading & Writing Files (Byte Stream)
2.3 Reading & Writing Files (Character Stream)
3 Multithreading
3.1 Process vs Thread · Multithreading Concept
3.2 Thread Life Cycle
3.3 Creating Threads (extend Thread)
3.4 Creating Threads (implement Runnable)
3.5 Thread Priorities
3.6 Synchronizing Threads
3.7 Inter-thread Communication
Page 2
BCS-403 • OOP with Java Unit II Notes
1 · Exception Handling
1.1 The Idea Behind Exception
In any Java program there can be three types of errors: Syntax Errors (missing semicolons,
caught by compiler), Logical Errors (bugs, wrong formulas), and Runtime Errors.
An exception is an unexpected, unwanted or abnormal event that occurs at runtime and
disrupts the normal flow of program instructions (e.g. dividing by zero, network failure, missing
file).
If not handled, the JVM abnormally terminates the program. Exception handling provides a
robust mechanism to handle situations gracefully.
1.2 Exceptions vs Errors
Feature Exception Error
Severity Moderate – application-level Critical – JVM/system-level
Recoverable? Yes – catch & recover No – must terminate
Examples NullPointerException, ArithmeticException OutOfMemoryError, StackOverflowError
Hierarchy Tree
Throwable
■■■ Error (StackOverflowError, OutOfMemoryError, ...)
■■■ Exception
■■■ RuntimeException [Unchecked]
■ ArithmeticException, NullPointerException, ...
■■■ IOException, SQLException, ... [Checked]
Types of Exceptions
Checked (Compile-Time): Checked by compiler. Must be handled with try-catch or declared
with throws. Examples: IOException, SQLException, ClassNotFoundException.
Unchecked (Run-Time): Not checked by compiler – JVM handles at runtime. Subclasses of
RuntimeException. Examples: ArithmeticException, NullPointerException,
ArrayIndexOutOfBoundsException.
1.3 Control Flow in Exceptions
Page 3
BCS-403 • OOP with Java Unit II Notes
1. Normal Flow: Code inside the try block executes line by line.
2. Exception Occurs: Remaining code in the try block is skipped.
3. Catching: JVM transfers control to the matching catch block.
4. Finally: Always executes regardless of exception.
Example – Handled Exception Flow
public class HandledExceptionFlow {
public static void main(String[] args) {
[Link]("Flow Step 1: Program Starts");
try {
[Link]("Flow Step 2: Entering Try Block");
int result = 10 / 0; // throws ArithmeticException
// This line is SKIPPED
[Link]("Flow Step 3: Inside Try Block");
} catch (ArithmeticException e) {
[Link]("Flow Step 4: Catch Block - " + [Link]());
} finally {
[Link]("Flow Step 5: Finally Block Executed");
}
[Link]("Flow Step 6: Program Ends Gracefully");
}
}
■ OUTPUT
Flow Step 1: Program Starts
Flow Step 2: Entering Try Block
Flow Step 4: Catch Block - / by zero
Flow Step 5: Finally Block Executed
Flow Step 6: Program Ends Gracefully
1.4 Exception Handling Keywords
Keyword Purpose
try Wraps 'risky' or error-suspecting code. Skips remaining code on exception.
catch Handles the exception object. Multiple catch blocks allowed for different types.
finally Always executes. Used for resource cleanup (close files, DB connections).
throw Explicitly throws an exception using new ExceptionType(msg).
throws Declared in method signature to warn callers about possible checked exceptions.
try-catch with Multiple Handlers
Page 4
BCS-403 • OOP with Java Unit II Notes
public class TryCatchDemo {
public static void main(String[] args) {
int result = 0;
try {
int dividend = [Link](args[0]);
int divisor = [Link](args[5]);
result = dividend / divisor; // risky code
} catch (ArithmeticException ae) {
[Link]("Second argument cannot be zero!");
} catch (ArrayIndexOutOfBoundsException aioobe) {
[Link]("Please input both dividend and divisor!");
}
[Link]("Result = " + result);
}
}
finally Keyword
public class FinallyDemo {
public static void main(String[] args) {
int result = 0;
try {
int dividend = 30;
int divisor = 0;
result = dividend / divisor;
} catch (ArithmeticException ae) {
[Link]("Cannot divide by zero!");
} finally {
// This ALWAYS executes
[Link]("Releasing Resources!");
}
[Link]("Result = " + result);
}
}
■ OUTPUT
Cannot divide by zero!
Releasing Resources!
Result = 0
throw Keyword
public class ThrowDemo {
public static void main(String[] args) {
try {
// Explicitly throwing a built-in exception
throw new NullPointerException("Object reference points to null!");
} catch (NullPointerException npe) {
[Link](npe);
}
}
}
Page 5
BCS-403 • OOP with Java Unit II Notes
throws Keyword
public class ThrowsDemo {
// Declaring that this method might throw an exception
public static void method() throws IllegalAccessException {
[Link]("Start");
throw new IllegalAccessException("Illegal Access !");
}
public static void main(String[] args) {
try {
method(); // Caller must handle it
} catch (IllegalAccessException iae) {
[Link]([Link]());
}
}
}
1.5 In-built Exceptions
Standard exception classes provided by the Java API, primarily in [Link] (also [Link],
[Link]). Divided into Checked and Unchecked.
public class InBuiltExceptionDemo {
public static void main(String[] args) {
[Link]("Program Execution Started...");
try {
// Scenario 1: ArithmeticException (Unchecked)
int a = 100, b = 0;
int result = a / b; // triggers ArithmeticException
[Link]("Result: " + result);
// Scenario 2: ArrayIndexOutOfBoundsException (Unchecked)
int[] arr = {10, 20, 30};
[Link](arr[6]); // out of bounds
} catch (ArithmeticException ae) {
[Link]("In-Built Exception: Arithmetic Error - Cannot divide by zero.");
} catch (ArrayIndexOutOfBoundsException aioobe) {
[Link]("In-Built Exception: Array Index is Out of Bounds.");
} catch (Exception e) {
[Link]("Some other exception: " + [Link]());
} finally {
[Link]("Finally block executed. Resource cleanup done.");
}
[Link]("Program Execution Completed Gracefully.");
}
}
Page 6
BCS-403 • OOP with Java Unit II Notes
■ OUTPUT
Program Execution Started...
In-Built Exception: Arithmetic Error - Cannot divide by zero.
Finally block executed. Resource cleanup done.
Program Execution Completed Gracefully.
1.6 User-Defined (Custom) Exceptions
When built-in exceptions do not cover specific business logic, create a custom exception by
extending Exception (checked) or RuntimeException (unchecked).
// Step 1: Create the Custom Exception Class
class InvalidAgeException extends Exception {
public InvalidAgeException(String message) {
super(message); // pass message to parent Throwable
}
}
// Step 2: Use it in a program
public class CustomExceptionDemo {
static void validateAge(int age) throws InvalidAgeException {
if (age < 18) {
throw new InvalidAgeException("Custom Error: Age must be 18+");
} else {
[Link]("Welcome!");
}
}
public static void main(String[] args) {
try {
validateAge(16);
} catch (InvalidAgeException e) {
[Link]([Link]());
}
}
}
■ OUTPUT
Custom Error: Age must be 18+
Page 7
BCS-403 • OOP with Java Unit II Notes
2 · Input / Output Basics
2.1 Introduction to Java I/O and Streams
Java performs all I/O operations using Streams. A stream is a logical entity representing a
continuous sequence of data from a source to a destination. All stream classes are in the
[Link] package.
Byte vs Character Streams
Feature Byte Stream Character Stream
Data Type 8-bit raw binary 16-bit Unicode characters
Reads/Writes byte-by-byte character-by-character
Suitability Images, audio, video, .exe Text files .txt .csv .html
Base Classes InputStream / OutputStream Reader / Writer
Concrete Classes FileInputStream, FileOutputStream FileReader, FileWriter
2.2 Byte Streams – Copying a File
FileInputStream / FileOutputStream handle 8-bit raw binary data. Always close resources in the
finally block.
Page 8
BCS-403 • OOP with Java Unit II Notes
import [Link].*;
public class ByteStreamFileDemo {
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream("[Link]");
fos = new FileOutputStream("[Link]");
[Link]("Available Bytes: " + [Link]());
int data;
// read() returns -1 at EOF
while ((data = [Link]()) != -1) {
[Link](data);
}
[Link]("Data Copied Successfully via Byte Stream!");
} catch (IOException e) {
[Link]("Exception Occurred: " + [Link]());
} finally {
try {
if (fis != null) [Link]();
if (fos != null) [Link]();
} catch (IOException e) {
[Link](e);
}
}
}
}
■ OUTPUT
Exception Occurred: [Link] (No such file or directory)
[When [Link] exists: Data Copied Successfully via Byte Stream!]
2.3 Character Streams – Read & Write Text File
FileReader / FileWriter handle 16-bit Unicode text. FileWriter(path, true) appends;
FileWriter(path) overwrites.
Page 9
BCS-403 • OOP with Java Unit II Notes
import [Link].*;
public class CharStreamFileDemo {
public static void main(String[] args) {
try {
// --- WRITING DATA ---
// 'true' enables Append Mode
FileWriter fw = new FileWriter("[Link]", true);
[Link]("Java I/O is based on Streams.\n");
[Link]("Character streams handle 16-bit text.\n");
[Link]();
[Link]();
[Link]("Text successfully written to file.");
// --- READING DATA ---
FileReader fr = new FileReader("[Link]");
int ch;
[Link]("\n--- File Content ---");
// read() returns -1 at end of stream
while ((ch = [Link]()) != -1) {
[Link]((char) ch);
}
[Link]();
} catch (IOException e) {
[Link]("I/O Error: " + [Link]());
}
}
}
■ OUTPUT
Text successfully written to file.
--- File Content ---
Java I/O is based on Streams.
Character streams handle 16-bit text.
Important I/O Concepts
• Always Use Try-Catch: All [Link] constructors/methods throw checked IOException or
FileNotFoundException.
• Resource Cleanup: Place close() calls in the finally block to prevent resource leaks.
• EOF Detection: Both FileInputStream and FileReader return -1 when end of stream is reached.
• FileReader has no available() method unlike FileInputStream.
Page 10
BCS-403 • OOP with Java Unit II Notes
3 · Multithreading
3.1 Process vs Thread
Feature Process Thread
Weight Heavyweight Lightweight sub-process
Memory Own isolated memory space Shared memory space
Context Switch Slow Fast
Communication Complex (IPC) Easy (shared memory)
CPU unit Whole program Smallest unit of execution
3.2 Thread Life Cycle
1. New (Born) State: Thread object created via new Thread(). start() not yet called.
2. Runnable (Ready) State: start() invoked. Thread is in the ready pool waiting for the
Scheduler.
3. Running State: Thread Scheduler picks the thread; run() executes on the CPU.
4. Blocked (Waiting) State: Thread pauses – calls sleep(), wait(), join() or awaits a lock.
5. Terminated (Dead) State: run() completed or stop() called. Cannot be restarted.
Life Cycle Transitions
start() End of run()
[New] ■■■■■■■■■■■■■■■ [Runnable] ■■■■■■■■■■■■■■■■ [Dead]
■ run() yield()
▼
[Running]
■ sleep() / wait() / join()
▼
[Blocked]
■ notify() / sleep expires
■■■■■■■■■■■■■■■■ [Runnable]
3.3 Creating Threads – Extending Thread Class
Page 11
BCS-403 • OOP with Java Unit II Notes
// Step 1: Extend [Link]
class MyThread extends Thread {
@Override
public void run() {
String name = [Link]().getName();
[Link](name + " has started.");
for (int i = 1; i <= 5; i++) {
try {
[Link](name + " executing iteration: " + i);
[Link](500); // pause 500 ms
} catch (InterruptedException e) {
[Link]("Exception: " + [Link]());
}
}
[Link](name + " has finished.");
}
}
public class ThreadExtendExample {
public static void main(String[] args) {
[Link]("Main thread started.");
MyThread t1 = new MyThread();
[Link]("Thread-A");
MyThread t2 = new MyThread();
[Link]("Thread-B");
[Link](); // Step 4: call start() – NOT run()
[Link]();
[Link]("Main thread ended.");
}
}
3.4 Creating Threads – Implementing Runnable
Page 12
BCS-403 • OOP with Java Unit II Notes
// Step 1: Implement [Link]
class MyRunnable implements Runnable {
@Override
public void run() {
String name = [Link]().getName();
[Link](name + " has started.");
for (int i = 1; i <= 5; i++) {
try {
[Link](name + " executing iteration: " + i);
[Link](500);
} catch (InterruptedException e) {
[Link]();
}
}
[Link](name + " has finished.");
}
}
public class RunnableInterfaceDemo {
public static void main(String[] args) {
[Link]("Main thread started.");
MyRunnable myTask = new MyRunnable();
// Step 4: pass Runnable into Thread constructor
Thread t1 = new Thread(myTask, "Child-Thread-1");
Thread t2 = new Thread(myTask, "Child-Thread-2");
// NOTE: [Link]() will NOT work
[Link]();
[Link]();
[Link]("Main thread finished.");
}
}
Extend Thread vs Implement Runnable
Aspect extend Thread implement Runnable
Inheritance Class cannot extend another class Class remains free to extend other class
Reusability Lower Higher – preferred
Start Thread [Link]() new Thread(runnable).start()
3.5 Thread Priorities
Java assigns each thread a priority (1–10). Higher-priority threads get more CPU time from the
Thread Scheduler.
Page 13
BCS-403 • OOP with Java Unit II Notes
// Thread priority constants
Thread.MIN_PRIORITY = 1
Thread.NORM_PRIORITY = 5 // default
Thread.MAX_PRIORITY = 10
// Usage
MyThread t1 = new MyThread();
[Link](Thread.MAX_PRIORITY); // 10
[Link]();
MyThread t2 = new MyThread();
[Link](Thread.MIN_PRIORITY); // 1
[Link]();
[Link]([Link]()); // 10
[Link]([Link]()); // 1
3.6 Synchronizing Threads
When multiple threads access the same shared resource simultaneously, it leads to data
inconsistency. Synchronization ensures only one thread accesses the shared resource at a
time using an intrinsic Monitor (Lock).
Method Level Synchronization
class Data {
int data;
Data(int data) { [Link] = data; }
// The 'synchronized' keyword locks the entire method
public synchronized void displayData(String threadName) {
[Link](threadName + " Start");
[Link](threadName + " data = " + data);
[Link](threadName + " End");
}
}
class DataAccess implements Runnable {
Data dataObj;
DataAccess(Data dataObj) { [Link] = dataObj; }
public void run() {
[Link]([Link]().getName());
}
}
public class ThreadSyncExample {
public static void main(String[] args) {
Data sharedData = new Data(10);
Thread thread1 = new Thread(new DataAccess(sharedData), "FIRST THREAD");
Thread thread2 = new Thread(new DataAccess(sharedData), "SECOND THREAD");
[Link]();
[Link]();
}
}
Page 14
BCS-403 • OOP with Java Unit II Notes
■ OUTPUT
FIRST THREAD Start
FIRST THREAD data = 10
FIRST THREAD End
SECOND THREAD Start
SECOND THREAD data = 10
SECOND THREAD End
Block Level Synchronization
Only the critical section is locked (more efficient than method-level).
public void run() {
// Unsynchronized code runs freely
// BLOCK LEVEL: lock acquired only on dataObj instance
synchronized (dataObj) {
[Link]([Link]().getName());
}
// Unsynchronized code resumes here
}
3.7 Inter-thread Communication
Mechanism allowing two synchronized threads to communicate. One thread pauses (wait) and
hands the lock to another to complete a prerequisite task.
Key Methods (from Object class)
Method Description
wait() Current thread releases its lock and enters waiting state.
notify() Wakes up a single thread waiting for the lock on this object.
notifyAll() Wakes up ALL threads waiting for the lock.
Producer-Consumer Example (Mother-Son)
Page 15
BCS-403 • OOP with Java Unit II Notes
class ToffeeContainer {
private boolean hasToffee = false;
// Producer Method
public synchronized void putToffee() {
while (hasToffee) {
try { wait(); } catch (InterruptedException e) { [Link](); }
}
[Link]("Mother puts a toffee in the container.");
hasToffee = true;
notify(); // wake up the son
}
// Consumer Method
public synchronized void takeToffee() {
while (!hasToffee) {
try { wait(); } catch (InterruptedException e) { [Link](); }
}
[Link]("Son takes the toffee from the container.");
hasToffee = false;
notify(); // wake up the mother
}
}
class Mother implements Runnable {
ToffeeContainer container;
Mother(ToffeeContainer c) { [Link] = c; }
public void run() {
for (int i = 1; i <= 5; i++) {
[Link]();
try { [Link](400); } catch (InterruptedException e) { [Link](e); }
}
}
}
class Son implements Runnable {
ToffeeContainer container;
Son(ToffeeContainer c) { [Link] = c; }
public void run() {
for (int i = 1; i <= 5; i++) {
[Link]();
try { [Link](300); } catch (InterruptedException e) { [Link](e); }
}
}
}
public class ThreadCommunicationExample {
public static void main(String[] args) {
ToffeeContainer container = new ToffeeContainer();
Thread mother = new Thread(new Mother(container));
Thread son = new Thread(new Son(container));
[Link]();
[Link]();
}
}
Page 16
BCS-403 • OOP with Java Unit II Notes
■ OUTPUT
Mother puts a toffee in the container.
Son takes the toffee from the container.
Mother puts a toffee in the container.
Son takes the toffee from the container.
Mother puts a toffee in the container.
Son takes the toffee from the container.
Mother puts a toffee in the container.
Son takes the toffee from the container.
Mother puts a toffee in the container.
Son takes the toffee from the container.
Quick Reference – Exception Methods
Method Class Use
getMessage() Throwable Returns error message string
toString() Throwable Returns class + message
printStackTrace() Throwable Prints full stack trace
getCause() Throwable Returns cause of exception
Page 17