OOP Concepts in Java - Encapsulation, Inheritance, Polymorphism | Java Codeex
1. What is OOP?
Object-Oriented Programming (OOP) is a programming paradigm that organises software design around data (objects) rather than functions and logic. Java is fundamentally an object-oriented language — almost everything in Java is an object.
OOP is built on four core pillars:
| Pillar | One-Line Definition | Key Java Construct |
|---|---|---|
| Encapsulation | Bundling data and methods; hiding internal details |
private fields +
getters/setters
|
| Inheritance | A class acquires properties of another class | extends |
| Polymorphism | One interface, many forms |
Overloading & @Override
|
| Abstraction | Hiding complexity, exposing only essentials |
abstract class / interface
|
Why OOP? OOP promotes code reusability, modularity, maintainability, and makes it easier to model real-world entities in software.
2. Classes and Objects
A class is a blueprint or template that defines
the state (fields) and behaviour (methods) that objects of its
type will have. An object is a concrete instance
of a class, created using the
new keyword.
// Class = blueprint
public class Car {
// Fields (state)
String brand;
String model;
int year;
double speed;
// Method (behaviour)
public void accelerate(double amount) {
speed += amount;
System.out.println(brand + " is now going at " + speed + " km/h");
}
public void brake(double amount) {
speed = Math.max(0, speed - amount);
System.out.println(brand + " slowed down to " + speed + " km/h");
}
public void displayInfo() {
System.out.println(year + " " + brand + " " + model);
}
}
// Main class to use the Car object
public class Main {
public static void main(String[] args) {
// Creating objects (instances) of Car
Car car1 = new Car(); // object 1
car1.brand = "Toyota";
car1.model = "Corolla";
car1.year = 2022;
Car car2 = new Car(); // object 2
car2.brand = "Honda";
car2.model = "Civic";
car2.year = 2023;
car1.displayInfo(); // 2022 Toyota Corolla
car1.accelerate(60); // Toyota is now going at 60.0 km/h
car2.displayInfo(); // 2023 Honda Civic
}
}
Toyota is now going at 60.0 km/h
2023 Honda Civic
Memory: Each object gets its own copy of instance fields but shares class-level (static) fields and methods.
3. Constructors
A constructor is a special method that is
automatically called when an object is created with
new. It has the same name as the class
and no return type.
Default Constructor
If you do not define any constructor, Java provides a no-argument default constructor automatically. Once you define any constructor, the default is no longer provided.
Parameterized Constructor
public class Car {
String brand;
String model;
int year;
// Default constructor
public Car() {
brand = "Unknown";
model = "Unknown";
year = 0;
}
// Parameterized constructor
public Car(String brand, String model, int year) {
this.brand = brand; // 'this' distinguishes field from parameter
this.model = model;
this.year = year;
}
// Copy constructor
public Car(Car other) {
this.brand = other.brand;
this.model = other.model;
this.year = other.year;
}
// Constructor chaining with this()
public Car(String brand) {
this(brand, "Generic", 2024); // calls parameterized constructor
}
public void display() {
System.out.println(year + " " + brand + " " + model);
}
}
public class Main {
public static void main(String[] args) {
Car c1 = new Car(); // default
Car c2 = new Car("Ford", "Mustang", 2023); // parameterized
Car c3 = new Car(c2); // copy
Car c4 = new Car("BMW"); // chained
c1.display(); // 0 Unknown Unknown
c2.display(); // 2023 Ford Mustang
c3.display(); // 2023 Ford Mustang
c4.display(); // 2024 BMW Generic
}
}
2023 Ford Mustang
2023 Ford Mustang
2024 BMW Generic
Note: this() must
be the first statement in a constructor. You cannot
call both this() and
super() in the same constructor.
4. The this Keyword
this is a reference to the
current object — the object whose method or
constructor is being called. It has three main uses:
public class Person {
String name;
int age;
// Use 1: Disambiguate fields from parameters
public Person(String name, int age) {
this.name = name; // 'this.name' = field, 'name' = parameter
this.age = age;
}
// Use 2: Call another constructor (constructor chaining)
public Person(String name) {
this(name, 0); // delegates to Person(String, int)
}
// Use 3: Pass current object as argument
public void register(Registry r) {
r.add(this); // passes the current Person object
}
public String getInfo() {
return this.name + ", age " + this.age;
}
}
class Registry {
public void add(Person p) {
System.out.println("Registered: " + p.getInfo());
}
}
public class Main {
public static void main(String[] args) {
Person p = new Person("Alice", 30);
System.out.println(p.getInfo()); // Alice, age 30
Registry reg = new Registry();
p.register(reg); // Registered: Alice, age 30
}
}