1. What is OOP?
OOP is a programming paradigm based on objects that contain data (attributes) and code
(methods). Objects are instances of classes, which act as blueprints.
2. Key Concepts
• Class: A template defining attributes and methods.
• Object: An instance of a class with its own data and behavior.
3. Procedural vs. Object-Oriented Programming
Feature Procedural Programming OOP
Approach Step-by-step execution Models real-world entities
Data Handling Global access, less secure Encapsulation for security
Code Reusability Limited High (Inheritance, Polymorphism)
Scalability Harder for large systems Easily scalable
Modularity Uses functions Uses classes and objects
4. Why Use OOP?
• Modularity: Divides code into reusable components.
• Code Reusability: Reduces duplication with inheritance.
• Scalability: Easily extends functionality.
• Security: Protects data using encapsulation.
5. Real-Life OOP Example (Bank System)
• Classes: Account, Customer, Transaction
• Objects: Raj’s Account, John’s Transaction
• Attributes: Account number, balance
• Methods: deposit(), withdraw(), transfer()
6. Class & Object in Java
Class Example:
class Employee {
private int salary;
public String employeeName;
public void setName(String s) {
employeeName = s;
Object Creation:
Employee obj1 = new Employee();
obj1.setName("Raj");
7. Attributes & Behaviors
• Attributes: Data inside an object (e.g., employeeName, salary).
• Behaviors: Actions an object can perform (e.g., setName(), getSalary()).
8. Memory Management in Java
• Stack Memory: Stores method calls, primitive data, and references.
• Heap Memory: Stores actual objects.
• Garbage Collection: Unused objects are automatically deleted.
Constructor in Java
Definition:
A constructor is a special method in a class used to initialize objects when they are created.
It has the same name as the class and no return type.
Types of Constructors:
1. Non-parameterized Constructor
o Does not take arguments.
o Used to initialize default values.
class Employee {
Employee() {
System.out.println("Employee created!");
}
}
2. Parameterized Constructor
o Accepts arguments to initialize object attributes.
class Employee {
String employeeName;
int salary;
Employee(String name, int salary) {
this.employeeName = name;
this.salary = salary;
3. Copy Constructor
o Creates a new object by copying attributes of an existing object.
class Employee {
String employeeName;
int salary;
Employee(Employee e) {
this.employeeName = e.employeeName;
this.salary = e.salary;
Concepts Related to Constructors:
• Constructor Chaining:
o One constructor calls another using this().
o Reduces code duplication.
• Constructor Overloading:
o Multiple constructors with different parameters allow flexible object creation.
class Employee {
String employeeName;
int salary;
Employee() {
this("Unknown", 0);
Employee(String name, int salary) {
this.employeeName = name;
this.salary = salary;
Advantages:
Object Initialization – Ensures objects start with default/user-defined values.
Code Reusability – Avoids repeated code for initializing objects.
Improved Readability – Organizes object creation logic effectively.
Encapsulation (Data Hiding)
• Definition: Bundling of data (attributes) and methods into a single unit (class) to
protect data from unauthorized access.
• Key Concept:
o Private attributes (fields) restrict direct access.
o Getter & Setter methods provide controlled access.
o Ensures data security, modularity, flexibility, and reduces complexity.
• Example:
class BankAccount {
private double balance;
public double getBalance() { return balance; }
public void deposit(double amount) { if (amount > 0) balance += amount; }
}
Access Modifiers
Defines the visibility of class members.
Modifier Class Package Subclass World
Public
Protected
Default
Private
1. Public: Accessible everywhere.
public String name;
public void showName() { System.out.println(name); }
2. Private: Accessible only within the class.
private double balance;
public double getBalance() { return balance; }
3. Protected: Accessible within the package and subclasses.
protected String type;
4. Default (No modifier): Accessible within the same package.
void showMessage()
{ System.out.println("Same package access."); }
Inheritance
Inheritance allows a child class to inherit properties and methods from a parent class,
promoting code reuse and hierarchy.
Types of Inheritance in Java
1. Single Inheritance - One class inherits from another.
2. Multilevel Inheritance - A class inherits from a child class, forming a chain.
3. Hierarchical Inheritance - Multiple classes inherit from a single parent.
Key Concepts
• Parent Class (Superclass) - Provides common properties and methods.
• Child Class (Subclass) - Inherits and can modify or extend parent class functionality.
• Method Overriding - A subclass provides a new implementation of a parent class
method.
• super Keyword - Calls parent class methods or constructor.
• Access Modifiers - Control inheritance visibility (public, protected, private).
Multiple Inheritance & Diamond Problem
• Java does NOT support multiple inheritance in classes to avoid conflicts.
• Solution: Java allows multiple inheritance via interfaces, not classes.
Polymorphism
Polymorphism allows the same method or object to behave differently based on context.
Types of Polymorphism in Java
1. Compile-Time Polymorphism (Static Polymorphism)
o Achieved using Method Overloading.
o Method name remains the same, but parameters differ.
o Resolved at compile-time.
2. Run-Time Polymorphism (Dynamic Polymorphism)
o Achieved using Method Overriding.
o Subclass provides a specific implementation of a parent class method.
o Resolved at runtime (Late binding).
Key Differences: Overloading vs Overriding
Feature Overloading Overriding
Dependency Same class Parent-Child classes
Parameters Must be different Must be same
Return Type Can be different Must be same
Execution Compile-time Run-time
Advantages of Inheritance & Polymorphism
✔ Code Reusability – Avoid code duplication.
✔ Extensibility – Add new features without modifying existing code.
✔ Maintainability – Centralized changes reduce errors.
✔ Dynamic Behavior – Enables runtime method resolution.
Abstraction in Java
Abstraction hides implementation details and shows only the essential features. It helps
simplify complex systems and improve maintainability.
Key Features
• Hides Complexity: Only necessary details are exposed.
• Abstract Methods: Declared without implementation, to be defined by subclasses.
• Concrete Methods: Have implementation in abstract classes.
Benefits
Simplifies the system
Improves maintainability
Increases reusability
Enhances security
Ways to Achieve Abstraction
1. Abstract Classes
o Cannot be instantiated directly.
o Can have both abstract and concrete methods.
abstract class Animal {
abstract void sound();
void eat() { System.out.println("This animal eats food."); }
2. Interfaces
o Contains only abstract methods (until Java 8).
o Implemented by classes to provide behavior.
interface Animal { void sound(); void eat(); }
class Dog implements Animal {
public void sound() { System.out.println("Bark"); }
public void eat() { System.out.println("Eating"); }
Static & Default Methods in Interfaces
1. Static Methods (Java 8+)
o Called using the interface name.
interface Example {
static void staticMethod() { System.out.println("Static method."); }
Example.staticMethod();
2. Default Methods (Java 8+)
o Allows interfaces to have method implementations.
interface Example {
default void defaultMethod() { System.out.println("Default method."); }
class Demo implements Example {}
new Demo().defaultMethod();
Why?
o Enables adding new methods to interfaces without breaking existing
implementations.
Common Questions
Can an abstract class extend another abstract class? Yes, it inherits methods but
doesn’t need to implement them unless it's concrete.
Can an abstract class have a constructor? Yes, but it cannot be instantiated directly.
The constructor runs when a subclass is created.
Interface in Java
• A blueprint defining method signatures without implementation.
• Example:
interface Animal {
void eat();
void sleep();
class Dog implements Animal {
public void eat() { System.out.println("Dog eats bones."); }
public void sleep() { System.out.println("Dog sleeps."); }
• Key Points:
o No instance variables (only public static final constants).
o No constructors (interfaces cannot be instantiated).
o A class can implement multiple interfaces.
Multiple Interface Implementation
interface Flyable { void fly(); }
interface Swimmable { void swim(); }
class Duck implements Flyable, Swimmable {
public void fly() { System.out.println("Duck flies."); }
public void swim() { System.out.println("Duck swims."); }
Default & Static Methods in Interfaces
• Default Method (Introduced in Java 8)
interface Example {
default void defaultMethod() {
System.out.println("This is a default method.");
class Demo implements Example {
public static void main(String[] args) {
new Demo().defaultMethod();
}
o Provides default behavior to interfaces.
o Helps in backward compatibility.
• Static Method in Interface
interface Utility {
static void staticMethod() {
System.out.println("This is a static method.");
class Test {
public static void main(String[] args) {
Utility.staticMethod();
o Cannot be overridden by implementing classes.
Interface Inheritance
interface Animal { void eat(); }
interface Mammal extends Animal { void walk(); }
class Human implements Mammal {
public void eat() { System.out.println("Human eats."); }
public void walk() { System.out.println("Human walks."); }
Static Members in Java
Static Variables
• Shared among all instances.
• Example:
class Counter {
static int count = 0;
Counter() { count++; }
o count is shared across objects.
Static Methods
• Called without creating an instance.
• Example:
class MathUtils {
static int add(int a, int b) { return a + b; }
class Main {
public static void main(String[] args) {
System.out.println(MathUtils.add(5, 3));
Static Block
• Used for initializing static variables.
• Example:
class Example {
static int value;
static { value = 10; System.out.println("Static block executed."); }
Static vs Non-Static Interaction
• Static methods cannot directly access non-static variables.
• Can access via an instance:
class Example {
int instanceVar = 10;
static void staticMethod() {
Example obj = new Example();
System.out.println("Instance variable: " + obj.instanceVar);
Advantages of Static Members
• Memory efficient (loaded once).
• Utility methods (e.g., Math.sqrt()).
• Static blocks initialize shared resources.
Utility Class Example
class Utils {
static void printMessage(String message) {
System.out.println(message);
class Main {
public static void main(String[] args) {
Utils.printMessage("Hello, Static!");
Inner Classes in Java
Inner classes are defined within another class, allowing better encapsulation and logical
grouping. They have access to all members of the outer class.
Types of Inner Classes:
1. Static Nested Classes
o Declared using the static keyword.
o Can access only static members of the outer class.
o No reference to an outer class instance.
o Example:
class Outer {
static int x = 100;
static class Nested {
void display() { System.out.println(x); }
2. Non-Static Inner Classes
o Requires an instance of the outer class.
o Can access both static and non-static members.
o Example:
class Outer {
int y = 42;
class Inner {
void show() { System.out.println(y); }
3. Local Inner Classes
o Defined inside a method/block.
o Can access only final or effectively final local variables.
o Example:
class Outer {
void method() {
int localVar = 10;
class LocalInner {
void show() { System.out.println(localVar); }
}
}
4. Anonymous Inner Classes
o Created without a name, often for one-time use.
o Useful for implementing interfaces or extending classes inline.
o Example:
abstract class Greeting {
abstract void sayHello();
public class Main {
public static void main(String[] args) {
Greeting g = new Greeting() {
void sayHello() { System.out.println("Hello, World!"); }
};
Relationships Between Classes
1. Association
• A general relationship where one class interacts with another.
• Types:
o One-to-One: Person ↔ Passport
o One-to-Many: Teacher ↔ Students
o Many-to-Many: Students ↔ Courses
2. Aggregation
• A "has-a" relationship with weak bonding.
• Objects can exist independently.
• Example: Department contains Employees, but employees exist independently.
class Department {
List<Employee> employees;
Department(List<Employee> emp) { this.employees = emp; }
3. Composition
• A strong "part-of" relationship where the dependent object cannot exist
independently.
• Example: House contains Rooms, and if the house is destroyed, rooms cease to exist.
class House {
List<Room> rooms = new ArrayList<>();
House() { rooms.add(new Room("Living Room")); }
Comparison Table
Aspect Association Aggregation Composition
Relationship General Weak Strong
Ownership No Has but doesn’t own Owns completely
Contained class can exist Contained class depends on
Independence Independent
independently whole
Teacher-
Example Employee-Department Car-Engine
Student
What is Object Cloning?
Object cloning is creating an exact copy of an object with a different memory location. It is
done using the Cloneable interface and the clone() method of the Object class.
Key Points:
• Cloned objects are independent of the original.
• Shallow cloning shares references, while deep cloning creates new copies.
Why Use Cloning?
• Efficiency: Avoids reinitialization of objects.
• Decoupling: Prevents unintended changes.
• State Preservation: Useful for undo/redo and caching.
• Prototyping: Used in the Prototype Design Pattern.
Working of Cloning
1. Cloneable Interface – Marker interface to enable cloning.
2. clone() Method – Performs a shallow copy by default.
Types of Cloning
1. Shallow Cloning
• Copies primitive fields and references (not the actual objects).
• Changes in shared references affect both original and cloned objects.
• Uses super.clone() method.
Example:
class Address {
String city;
Address(String city) { this.city = city; }
class Person implements Cloneable {
String name;
Address address;
Person(String name, Address address) { this.name = name; this.address = address; }
protected Object clone() throws CloneNotSupportedException { return super.clone(); }
2. Deep Cloning
• Creates independent copies of all objects, including nested objects.
• Requires manual cloning of reference-type fields.
Example:
class Address implements Cloneable {
String city;
Address(String city) { this.city = city; }
protected Object clone() throws CloneNotSupportedException { return (Address)
super.clone(); }
class Person implements Cloneable {
String name;
Address address;
Person(String name, Address address) { this.name = name; this.address = address; }
protected Object clone() throws CloneNotSupportedException {
Person cloned = (Person) super.clone();
cloned.address = (Address) address.clone();
return cloned;
Shallow vs Deep Cloning
Aspect Shallow Cloning Deep Cloning
Primitive Fields Copied Copied
Object References Shared Independent
Nested Objects Overriding? No Yes
Use Case Simple objects Objects with mutable references
Exception Handling in Java
Exception handling manages runtime errors and ensures the normal flow of a program.
Why Exception Handling?
• Prevents program crashes.
• Improves debugging.
• Separates normal and error-handling code.
• Ensures proper resource management.
Try-Catch Mechanism
• try block: Contains risky code.
• catch block: Handles exceptions.
• finally block: Always executes, used for resource cleanup.
Example:
try {
int num = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Cannot divide by zero!");
} finally {
System.out.println("Execution completed.");
throw vs throws
Feature throw throws
Declare that a method may throw
Purpose Manually throw an exception
exceptions
Usage Inside a method In method signature
throw new
Example void divide() throws ArithmeticException
ArithmeticException("Error");
Custom Exceptions
User-defined exceptions help define specific error conditions.
class CustomException extends Exception {
CustomException(String message) {
super(message);
Checked vs Unchecked Exceptions
Type Description Examples
Checked Must be handled (compile-time) IOException, SQLException
Type Description Examples
Unchecked Occur at runtime NullPointerException, ArithmeticException
Example:
• Checked:
File file = new File("test.txt");
Scanner reader = new Scanner(file);
• Unchecked:
int num = 10 / 0;
Real-Life Example
Handling file exceptions:
try {
File file = new File("data.txt");
Scanner sc = new Scanner(file);
} catch (FileNotFoundException e) {
System.out.println("File not found!");
Generics in Java (Short Notes)
Introduction
• Introduced in Java 5 to ensure type safety and code reusability.
• Allows defining classes, interfaces, and methods that work with multiple data types.
Key Benefits
✔ Prevents ClassCastException (runtime error due to invalid type casting).
✔ Provides compile-time type checking.
✔ Reduces code redundancy.
Example Without Generics (Before Java 5)
ArrayList list = new ArrayList();
list.add("Hello");
list.add(100);
String str = (String) list.get(1);
Drawbacks: Allows different types, requires type casting, risks ClassCastException.
Example With Generics
ArrayList<String> list = new ArrayList<>();
list.add("Hello");
// list.add(100); // Compile-time error (Prevents mistakes)
String str = list.get(0);
Advantages: Type safety, no explicit type casting, better maintainability.
1. Generic Classes
• A single class works for multiple data types.
Syntax:
class Box<T> {
private T value;
public void set(T value) { this.value = value; }
public T get() { return value; }
Benefits: Works for any data type, improves code reusability.
2. Generic Methods
• Allows different data types in the same method.
Syntax:
class Example {
public <T> void print(T data) {
System.out.println("Data: " + data);
Benefits: Works for multiple types, avoids method overloading.
3. Bounded Type Parameters
• Restricts generic types to specific parent classes (ensures type safety).
Syntax:
class NumericBox<T extends Number> {
private T num;
public double square() { return num.doubleValue() * num.doubleValue(); }
Allowed: Integer, Double, etc. Not Allowed: String.
4. Wildcard Types (?)
• Used when the exact type is unknown.
✔ Upper Bounded (? extends T) – Allows reading, restricts writing.
public static void printList(List<? extends Number> list) {
for (Number num : list) { System.out.print(num + " "); }
✔ Lower Bounded (? super T) – Allows writing, restricts reading.
public static void addNumbers(List<? super Integer> list) {
list.add(10);
5. Raw Types (Not Recommended)
• Using generics without specifying type parameters.
Box rawBox = new Box();
rawBox.set("Hello");
Integer num = (Integer) rawBox.get();
Avoid raw types to prevent runtime errors.
6. Type Erasure
• Generics exist only at compile-time (removed at runtime).
• Compiler replaces generic types with raw types (Object or upper bound).
class Box<T> {
T value;
void set(T value) {
this.value = value;
T get() {
return value;
✔ After Compilation (Erased Generics):
class Box {
Object value;
void set(Object value) {
this.value = value;
Object get() {
return value;
}}
Impact: No runtime type information, cannot use instanceof with generics, generic
arrays not allowed.
Summary
Feature Purpose Key Benefit
Generic Class Works for multiple types Code reuse
Feature Purpose Key Benefit
Generic Method Works with different types Avoids overloading
Bounded Type (extends) Restricts to specific type Type safety
Wildcards (?) Allows unknown types Flexibility
Raw Types Uses generics without type Risky, avoid using
Type Erasure Removes generics at runtime Backward compatibility
File Handling in OOPs (Java)
File Handling refers to reading and writing files for data storage and retrieval.
Common File Operations
• Create a file
• Read from a file
• Write to a file
• Append data
• Delete a file
import java.io.File;
import java.io.IOException;
class Main {
public static void main(String[] args) {
try {
File file = new File("example.txt");
if (file.createNewFile())
System.out.println("File created: " + file.getName());
} catch (IOException e) {
e.printStackTrace();
}
Handling Errors: IOException is used for handling errors like invalid paths or permission
issues.
File Class (java.io.File)
• createNewFile(): Creates a file
• exists(): Checks file existence
• delete(): Deletes a file
• getAbsolutePath(): Returns file path
• length(): Returns file size
• canRead(), canWrite(): Checks permissions
Reading and Writing Files
Writing to a file using BufferedWriter:
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
class Main {
public static void main(String[] args) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter("example.txt"))) {
writer.write("Hello, File Handling!");
} catch (IOException e) {
e.printStackTrace();
Reading a file using BufferedReader:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
class Main {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("example.txt"))) {
System.out.println(reader.readLine());
} catch (IOException e) {
e.printStackTrace();
Logging with File Handling
import java.io.*;
class Logger {
private String path;
Logger(String path) throws IOException {
this.path = path;
new File(path).createNewFile();
void log(String message) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(path, true))) {
writer.write(message);
writer.newLine();
} catch (IOException e) {
System.out.println("Logging failed!");
}}
Common Issues
• FileNotFoundException: Check file existence before reading.
• IOException: Handle with try-catch.
• Resource Leaks: Use try-with-resources to auto-close files