The 4 Pillars of OOP in Java: Encapsulation, Inheritance, Polymorphism & Abstraction with Code
Author: Bhuban Subedi | Subject: Object-Oriented Programming in Java (CACS205) | Semester: Third Semester
When shifting from procedural programming in C to Object-Oriented Programming (OOP) in Java, the paradigm shift can feel challenging.
In C, we organized software around sequential procedures and functions manipulating raw data. In Java, everything revolves around Objects—self-contained entities that bundle both state (data fields) and behavior (methods) together.
In the Tribhuvan University (TU) BCA Third Semester OOP in Java (CACS205) board examination, questions regarding the 4 Core Pillars of OOP, the distinction between Method Overloading vs Method Overriding, and Abstract Classes vs Interfaces form the cornerstone of 10-mark long questions.
In this guide, we will break down each pillar with real-world analogies, examine memory mechanics, understand key Java keywords (this, super, final), and write clean, compilable Java code.
1. High-Level Blueprint of the 4 Pillars of OOP
+-----------------------------+
| OBJECT-ORIENTED JAVA |
+--------------+--------------+
|
+----------------------+--------------+--------------+----------------------+
| | | |
v v v v
+---------------+ +---------------+ +---------------+ +---------------+
| ENCAPSULATION | | INHERITANCE | | POLYMORPHISM | | ABSTRACTION |
| Data Hiding & | | Code Reusability | Many Forms: | | Hiding Impl. |
| Getter/Setter | | (extends) | | Overload/Ride | | Interface/Abs |
+---------------+ +---------------+ +---------------+ +---------------+
2. Pillar 1: Encapsulation (Data Hiding & Security)
Encapsulation is the mechanism of wrapping data (instance variables) and code acting on the data (methods) together into a single unit (class), while restricting direct access to components from outside the class.
How to Achieve Encapsulation in Java:
- Declare class instance variables as
private. - Provide
publicgetter and setter methods to inspect and modify field values with validation logic.
Practical Code Example:
// Encapsulated Class
class BankAccount {
private String accountNumber;
private double balance; // Protected from unauthorized direct access
// Constructor
public BankAccount(String accountNumber, double initialBalance) {
this.accountNumber = accountNumber;
if (initialBalance >= 0) {
this.balance = initialBalance;
} else {
this.balance = 0.0;
}
}
// Getter for Balance
public double getBalance() {
return this.balance;
}
// Controlled Setter / Deposit method with validation
public void deposit(double amount) {
if (amount > 0) {
this.balance += amount;
System.out.println("Successfully deposited Rs. " + amount);
} else {
System.out.println("Invalid deposit amount!");
}
}
public void withdraw(double amount) {
if (amount > 0 && amount <= this.balance) {
this.balance -= amount;
System.out.println("Successfully withdrew Rs. " + amount);
} else {
System.out.println("Insufficient funds or invalid amount!");
}
}
}
3. Pillar 2: Inheritance (Code Reusability & Hierarchy)
Inheritance is the mechanism where a new child class (subclass / derived class) inherits properties and methods from an existing parent class (superclass / base class) using the extends keyword.
Types of Inheritance:
- Single Inheritance: Class B extends Class A.
- Multilevel Inheritance: Class C extends Class B, and Class B extends Class A.
- Hierarchical Inheritance: Class B and Class C both extend Class A.
- Multiple Inheritance: (Not supported in Java classes to prevent the Diamond Problem; achieved exclusively via Interfaces).
[ Person ] (Parent / Superclass)
^
| extends
[ Student ] (Child / Subclass)
The Role of super Keyword:
super()invokes the parent class constructor.super.methodName()calls an overridden parent method.super.fieldNameaccesses hidden parent instance variables.
4. Pillar 3: Polymorphism (Compile-Time vs Runtime)
Polymorphism (from Greek: “having multiple forms”) is the ability of an object or method to behave differently based on the context.
+------------------------------------+------------------------------------+
| Compile-Time Polymorphism (Static) | Runtime Polymorphism (Dynamic) |
+------------------------------------+------------------------------------+
| **Method Overloading** | **Method Overriding** |
+------------------------------------+------------------------------------+
| Methods in the same class share | Subclass provides specific |
| the same name but different | implementation of a parent method |
| parameter lists (type, count). | with the exact same signature. |
+------------------------------------+------------------------------------+
| Resolved at compile time by compiler| Resolved at runtime via Dynamic |
| based on argument types. | Method Dispatch. |
+------------------------------------+------------------------------------+
5. Pillar 4: Abstraction (Abstract Classes vs Interfaces)
Abstraction is the process of hiding internal implementation details and showing only essential features to the user.
+------------------------------------+------------------------------------+
| Abstract Class | Interface |
+------------------------------------+------------------------------------+
| Declared using `abstract` keyword. | Declared using `interface` keyword.|
+------------------------------------+------------------------------------+
| Can have both abstract (unimplemented) | Prior to Java 8, could only have |
| and concrete (implemented) methods.| purely abstract methods. |
+------------------------------------+------------------------------------+
| Can have instance variables and | All variables are implicitly |
| constructors. | `public static final` (constants). |
+------------------------------------+------------------------------------+
| Subclass uses `extends` (Single). | Subclass uses `implements` (Multi).|
+------------------------------------+------------------------------------+
6. Complete Compilable Java Program Integrating All 4 Pillars
// ==========================================
// PILLAR 4: ABSTRACTION (Interface & Abstract Class)
// ==========================================
interface Payable {
double calculateSalary(); // Abstract method
}
abstract class Employee implements Payable {
// PILLAR 1: ENCAPSULATION
private int empId;
private String name;
public Employee(int empId, String name) {
this.empId = empId;
this.name = name;
}
public int getEmpId() { return empId; }
public String getName() { return name; }
// Concrete method shared by all subclasses
public void displayProfile() {
System.out.println("Employee ID: " + empId + " | Name: " + name);
}
}
// ==========================================
// PILLAR 2: INHERITANCE (Subclasses extending Employee)
// ==========================================
class FullTimeEmployee extends Employee {
private double monthlySalary;
public FullTimeEmployee(int empId, String name, double monthlySalary) {
super(empId, name); // Calling parent constructor
this.monthlySalary = monthlySalary;
}
// PILLAR 3: RUNTIME POLYMORPHISM (Method Overriding)
@Override
public double calculateSalary() {
return monthlySalary;
}
}
class PartTimeEmployee extends Employee {
private int hoursWorked;
private double hourlyRate;
public PartTimeEmployee(int empId, String name, int hoursWorked, double hourlyRate) {
super(empId, name);
this.hoursWorked = hoursWorked;
this.hourlyRate = hourlyRate;
}
@Override
public double calculateSalary() {
return hoursWorked * hourlyRate;
}
}
// ==========================================
// MAIN CLASS DEMONSTRATING EXECUTION
// ==========================================
public class OOPMasterDemo {
public static void main(String[] args) {
System.out.println("==========================================");
System.out.println(" TU BCA OOP IN JAVA MASTER PROGRAM ");
System.out.println("==========================================\n");
// Polymorphic Array: Storing subclass objects in parent references
Employee[] staff = new Employee[2];
staff[0] = new FullTimeEmployee(101, "Aayush Sharma", 65000.0);
staff[1] = new PartTimeEmployee(102, "Pooja Shrestha", 80, 500.0);
for (Employee emp : staff) {
emp.displayProfile();
// Dynamic Method Dispatch executes the appropriate calculateSalary()
System.out.printf("Calculated Monthly Payout: Rs. %.2f\n\n", emp.calculateSalary());
}
}
}
Frequently Asked Questions (FAQ)
Q1: Why does Java not support Multiple Inheritance with classes?
If two parent classes (A and B) declare the same method void print(), and child class C extends both, calling c.print() creates ambiguity regarding which parent implementation to execute (known as the Diamond Problem). Java avoids this by allowing multiple inheritance only through Interfaces.
Q2: What is the significance of the final keyword in Java?
- Final Variable: Value becomes constant and cannot be reassigned.
- Final Method: Cannot be overridden by any subclass.
- Final Class: Cannot be inherited/extended (e.g.,
java.lang.String).



