DEV Community

Madhavan G
Madhavan G

Posted on

What Is OOP in Java? Classes, Objects, and the Four Pillars.

What is OOPs?

OOPs stands for Object-Oriented Programming.

It is a programming style where we create programs using objects. These objects represent real-world things like a student, a car, a mobile phone, or a bank account.

Instead of writing one huge program with everything mixed together, OOP helps us organize our code into small, manageable pieces.

In Java, everything is centered around classes and objects, mimicking real-world entities to make code modular, reusable, and easy to maintain.

Think of it like organizing your room.

  • Clothes go into one cupboard.
  • Books go on one shelf.
  • Shoes stay in one place.

Everything has its own place.

OOP does the same thing for our code.


Why Do We Need OOP?

Imagine you are building a School Management System.

You need to store information about hundreds of students.

Without OOP, your code might look like this:

String student1Name = "Rahul";
int student1Age = 20;

String student2Name = "Anjali";
int student2Age = 21;

String student3Name = "John";
int student3Age = 19;
Enter fullscreen mode Exit fullscreen mode

Now imagine there are 1,000 students.

Your program becomes huge, repetitive, and difficult to manage.

Now let's solve the same problem using OOP.

Student s1 = new Student();
Student s2 = new Student();
Student s3 = new Student();
Enter fullscreen mode Exit fullscreen mode

That's it!

We create one blueprint called Student, and then we create as many students as we need.

This makes the code:

  • Cleaner
  • Easier to understand
  • Easier to update
  • Easier to reuse

What is a Class?

A class is simply a blueprint or template.

Let's use a real-life example.

Suppose an architect designs a house.

The drawing is called a blueprint.

The blueprint tells us:

  • Where the doors are
  • Where the windows are
  • Where the kitchen is

But can you live inside the blueprint?

No!

It is only a design.

Similarly, in Java:

A class is only a blueprint.

Example:

class Student {

    String name;
    int age;

}
Enter fullscreen mode Exit fullscreen mode

This class only describes what a student looks like.

It doesn't create a real student yet.


What is an Object?

An object is the real thing created from a class.

Using our house example:

  • Blueprint → Class
  • Real House → Object

In Java:

Student s1 = new Student();
Enter fullscreen mode Exit fullscreen mode

Now a real student object has been created.

Let's give it some data.

s1.name = "Rahul";
s1.age = 20;
Enter fullscreen mode Exit fullscreen mode

Now this object represents a real student.

Another object can store different data.

Student s2 = new Student();

s2.name = "Anjali";
s2.age = 22;
Enter fullscreen mode Exit fullscreen mode

Both objects are created from the same class, but they hold different information.


Properties and Methods

Every object has two things:

1. Properties (Data)

Properties describe the object.

For a Student:

  • Name
  • Age
  • Roll Number

For a Car:

  • Brand
  • Color
  • Speed

2. Methods (Actions)

Methods describe what an object can do.

For a Student:

  • Study
  • Attend Class
  • Write Exam

For a Car:

  • Start
  • Stop
  • Drive

Example:

class Student {

    String name;

    void study() {
        System.out.println(name + " is studying.");
    }

}
Enter fullscreen mode Exit fullscreen mode

Using the object:

Student s1 = new Student();

s1.name = "Rahul";

s1.study();
Enter fullscreen mode Exit fullscreen mode

Output:

Rahul is studying.
Enter fullscreen mode Exit fullscreen mode

Example

Let's create a simple Car class.

class Car {

    String brand;
    String color;

    void start() {
        System.out.println("Car Started");
    }

    void stop() {
        System.out.println("Car Stopped");
    }

}
Enter fullscreen mode Exit fullscreen mode

Now create an object.

public class Main {

    public static void main(String[] args) {

        Car car1 = new Car();

        car1.brand = "Toyota";
        car1.color = "White";

        car1.start();
        car1.stop();

    }

}
Enter fullscreen mode Exit fullscreen mode

Output:


Why Is OOP So Powerful?

Suppose a car company manufactures 10,000 cars.

Do they design every car from scratch?

No.

They create one design and use it to build thousands of cars.

OOP works the same way.

One class.

Many objects.

Example:

Car car1 = new Car();
Car car2 = new Car();
Car car3 = new Car();
Enter fullscreen mode Exit fullscreen mode

Each object can have different values.

Car 1
Brand : BMW
Color : Black

Car 2
Brand : Audi
Color : White

Car 3
Brand : Toyota
Color : Red
Enter fullscreen mode Exit fullscreen mode

The Four Pillars of Object-Oriented Programming (OOPs)

1. Encapsulation – Protecting Your Data

What is Encapsulation?

Encapsulation means wrapping data (variables) and methods (functions) together into a single unit (class) while controlling how the data is accessed.

In simple words, don't allow anyone to change your data directly. Instead, provide controlled methods to access or modify it.

Imagine you have a bank account.

You cannot directly go into the bank's database and change your account balance.

Instead, you use services like:

  • Deposit money
  • Withdraw money
  • Check balance

The bank controls how your balance changes. This is exactly how encapsulation works.


Real-Life Example

Think about an ATM.

You can:

  • Insert your card
  • Enter your PIN
  • Withdraw money
  • Check your balance

But you cannot directly open the ATM and change the amount of money inside.

The ATM hides its internal data and only allows certain operations.

This is encapsulation.


What Are Getters and Setters in Encapsulation?

When we make a variable private, it cannot be accessed directly from outside the class.

So how do we read or update its value?

This is where getters and setters come in.

  • A Getter is a method that returns (gets) the value of a private variable.
  • A Setter is a method that updates (sets) the value of a private variable.

Think of them as controlled doors to your data.

Instead of allowing anyone to access your data directly, you decide how people can read or modify it.


Why Do We Use Getters and Setters?

Imagine you're creating a Student class.

You don't want someone to accidentally assign an invalid age like -10 or 500.

Without getters and setters, someone could write:

student.age = -10;
Enter fullscreen mode Exit fullscreen mode

This doesn't make sense because a person's age cannot be negative.

Instead, we make the variable private and provide a setter method that checks whether the value is valid before saving it.


Example Without Encapsulation

class Student {

    public int age;

}
Enter fullscreen mode Exit fullscreen mode
Student student = new Student();

student.age = -10;

System.out.println(student.age);
Enter fullscreen mode Exit fullscreen mode

Output:

-10
Enter fullscreen mode Exit fullscreen mode

The program accepts an invalid age because there is no validation.


Example With Encapsulation

class Student {

    private int age;

    public void setAge(int age) {

        if (age > 0) {
            this.age = age;
        } else {
            System.out.println("Invalid age");
        }

    }

    public int getAge() {
        return age;
    }

}
Enter fullscreen mode Exit fullscreen mode

Now use the class.

Student student = new Student();

student.setAge(20);

System.out.println(student.getAge());
Enter fullscreen mode Exit fullscreen mode

Output:

20
Enter fullscreen mode Exit fullscreen mode

Now try this:

student.setAge(-10);
Enter fullscreen mode Exit fullscreen mode

Output:

Invalid age
Enter fullscreen mode Exit fullscreen mode

The invalid value is rejected because the setter method checks the data before storing it.


Understanding the Getter

public int getAge() {
    return age;
}
Enter fullscreen mode Exit fullscreen mode

Let's understand this line by line.

  • public → Anyone can call this method.
  • int → The method returns an integer.
  • getAge() → Method name. By convention, getter methods start with get.
  • return age; → Sends the value of the private variable back to the caller.

When you write:

System.out.println(student.getAge());
Enter fullscreen mode Exit fullscreen mode

The getter returns the value stored in age, which is then printed.


Understanding the Setter

public void setAge(int age) {
    this.age = age;
}
Enter fullscreen mode Exit fullscreen mode

Let's break it down.

  • public → Anyone can call this method.
  • void → The method doesn't return any value.
  • setAge(int age) → Accepts a new age as a parameter.
  • this.age = age; → Stores the given value in the object's age variable.

Notice that both the parameter and the instance variable are named age.

The keyword this refers to the current object's variable.

So:

this.age = age;
Enter fullscreen mode Exit fullscreen mode

means:

"Store the parameter age into this object's age variable."

Without this, Java wouldn't know which age you mean because both have the same name.


Real-Life Analogy

Think of a school office.

The student's records are stored in a secure room.

Students cannot enter the room and edit their records directly.

Instead:

  • If they want to see their details, they ask the office staff. (Getter)
  • If they want to update their address or phone number, they submit a request to the office staff. (Setter)

The office staff checks whether the information is valid before updating the records.

This is exactly how getters and setters work in Java.


Benefits of Using Getters and Setters

Using getters and setters provides several advantages:

  • Protects important data from direct access.
  • Allows validation before updating values.
  • Prevents invalid data from entering the program.
  • Makes the code easier to maintain.
  • Gives you full control over how data is accessed and modified.

That's why getters and setters are considered a fundamental part of Encapsulation in Java.


Why is Encapsulation Important?

Without encapsulation:

  • Anyone can modify your data.
  • Invalid values can enter your program.
  • Bugs become more common.

With encapsulation:

  • Data stays safe.
  • Validation becomes easier.
  • The program becomes more secure.
  • Future changes become simpler because all updates go through methods.

2. Inheritance – Reusing Existing Code

What is Inheritance?

Inheritance allows one class to use the properties and methods of another class.

Instead of writing the same code again and again, we reuse it.

This saves both time and effort.


Real-Life Example

Imagine a family.

A child inherits certain characteristics from their parents.

For example:

  • Eye color
  • Hair color
  • Height

Similarly, in Java, one class can inherit features from another class.


Another Example

Suppose we have an Animal class.

Every animal can:

  • Eat
  • Sleep
  • Walk

Instead of writing these methods separately for Dog, Cat, Cow, and Horse, we create one Animal class.

Animal
   |
   +-- Dog
   |
   +-- Cat
   |
   +-- Cow
Enter fullscreen mode Exit fullscreen mode

Now every animal automatically gets these common features.


Java Example

class Animal {

    void eat() {
        System.out.println("Animal is eating");
    }

}

class Dog extends Animal {

    void bark() {
        System.out.println("Dog is barking");
    }

}
Enter fullscreen mode Exit fullscreen mode

Using the object:

Dog dog = new Dog();

dog.eat();

dog.bark();
Enter fullscreen mode Exit fullscreen mode

Output:

Animal is eating
Dog is barking
Enter fullscreen mode Exit fullscreen mode

Notice that the Dog class didn't define the eat() method.

It inherited it from the Animal class.


Why is Inheritance Important?

Imagine writing software for a zoo.

There may be hundreds of animal types.

Instead of rewriting common code for every animal, inheritance lets us write it once and reuse it everywhere.

Benefits include:

  • Less duplicate code
  • Easier maintenance
  • Faster development
  • Better organization

3. Polymorphism – One Method, Many Behaviors

What is Polymorphism?

The word Polymorphism comes from two Greek words:

  • Poly = Many
  • Morphism = Forms

Together, it means many forms.

In java,the same method name can behave differently depending on the object that uses it.

In Java a concept that allows a single action, method, or object to take on multiple formsis called polymorphism.


Real-Life Example

Imagine a person saying:

"I am speaking."

The action is the same—speaking—but the language can be different.

  • English
  • Tamil
  • Hindi
  • French

The action remains the same, but the behavior changes.

This is polymorphism.


Animal Example

Every animal makes a sound.

But every animal sounds different.

Dog → Bark

Cat → Meow

Cow → Moo
Enter fullscreen mode Exit fullscreen mode

The method name can be sound(), but each class provides its own implementation.


Java Example

class Animal {

    void sound() {
        System.out.println("Animal makes a sound");
    }

}

class Dog extends Animal {

    void sound() {
        System.out.println("Dog barks");
    }

}

class Cat extends Animal {

    void sound() {
        System.out.println("Cat meows");
    }

}
Enter fullscreen mode Exit fullscreen mode

Using the objects:

Dog dog = new Dog();
Cat cat = new Cat();

dog.sound();

cat.sound();
Enter fullscreen mode Exit fullscreen mode

Output:

Dog barks

Cat meows
Enter fullscreen mode Exit fullscreen mode

The method name is the same, but the output changes depending on the object.


Types of Polymorphism in Java

In Java, polymorphism is mainly divided into two types:

  1. Compile-time Polymorphism (Method Overloading)
  2. Run-time Polymorphism (Method Overriding)

Let's understand each one with simple examples.


1. Compile-time Polymorphism (Method Overloading)

What is Compile-time Polymorphism?

Compile-time polymorphism happens when multiple methods have the same name but different parameter lists.

The Java compiler decides which method to call while compiling the program, which is why it is called compile-time polymorphism.

This is also known as Method Overloading.


Real-Life Example

Think about a calculator.

The calculator has an Add button.

You can use it to add:

  • Two numbers
  • Three numbers
  • Decimal numbers

The action is still Add, but it works differently depending on the inputs.

This is exactly how method overloading works.


Java Example

class Calculator {

    int add(int a, int b) {
        return a + b;
    }

    int add(int a, int b, int c) {
        return a + b + c;
    }

    double add(double a, double b) {
        return a + b;
    }

}
Enter fullscreen mode Exit fullscreen mode

Using the methods:

Calculator calc = new Calculator();

System.out.println(calc.add(10, 20));

System.out.println(calc.add(10, 20, 30));

System.out.println(calc.add(10.5, 20.5));
Enter fullscreen mode Exit fullscreen mode

Output:

30
60
31.0
Enter fullscreen mode Exit fullscreen mode

Notice that all three methods have the same name (add), but they accept different parameters.

The compiler decides which method to call based on the arguments you provide.

That's why this is called Compile-time Polymorphism.


Rules for Method Overloading

To overload a method:

  • The method name must be the same.
  • The parameter list must be different (different number or types of parameters).
  • Changing only the return type is not enough.

For example, this is not allowed:

int add(int a, int b) { }

double add(int a, int b) { }
Enter fullscreen mode Exit fullscreen mode

These methods have the same name and the same parameters, so Java will report an error.


2. Run-time Polymorphism (Method Overriding)

What is Run-time Polymorphism?

Run-time polymorphism happens when a child class provides its own implementation of a method that already exists in the parent class.

The decision about which method to execute is made while the program is running, so it is called run-time polymorphism.

This is also known as Method Overriding.


Real-Life Example

Every animal makes a sound.

But the sound is different for each animal.

  • Dog → Bark
  • Cat → Meow
  • Cow → Moo

The action is the same (sound()), but each animal performs it differently.

This is method overriding.


Java Example

class Animal {

    void sound() {
        System.out.println("Animal makes a sound");
    }

}

class Dog extends Animal {

    @Override
    void sound() {
        System.out.println("Dog barks");
    }

}

class Cat extends Animal {

    @Override
    void sound() {
        System.out.println("Cat meows");
    }

}
Enter fullscreen mode Exit fullscreen mode

Now let's create the objects.

Animal animal;

animal = new Dog();
animal.sound();

animal = new Cat();
animal.sound();
Enter fullscreen mode Exit fullscreen mode

Output:

Dog barks
Cat meows
Enter fullscreen mode Exit fullscreen mode

Notice that the variable type is Animal, but the method that runs depends on the actual object (Dog or Cat).

Java decides this at runtime, which is why it is called Run-time Polymorphism.


Compile-time vs Run-time Polymorphism

Feature Compile-time Polymorphism Run-time Polymorphism
Also Known As Method Overloading Method Overriding
Decision Made During compilation During program execution
Requires Inheritance No Yes
Method Name Same Same
Parameters Must be different Must be the same
Example add(int, int) and add(int, int, int) Animal.sound() overridden by Dog.sound()

Easy Trick to Remember

A simple way to remember the difference is:

Method Overloading = Same class + Different parameters

Method Overriding = Parent class + Child class + Same method


Why is Polymorphism Important?

Polymorphism makes programs:

  • Flexible
  • Easy to extend
  • Easy to maintain.

4. Abstraction – Hiding Complexity

What is Abstraction?

Abstraction means showing only the important features while hiding unnecessary implementation details.

Users don't need to know how everything works internally.

They only need to know how to use it.


Real-Life Example 1 – Driving a Car

When you drive a car, you use:

  • Steering wheel
  • Accelerator
  • Brake
  • Gear

But do you know exactly how the engine, fuel injection system, and transmission work?

Probably not.

You don't need to.

The complex internal details are hidden.

This is abstraction.


Real-Life Example 2 – Mobile Phone

You press the camera button.

The phone automatically:

  • Opens the camera
  • Focuses the lens
  • Adjusts brightness
  • Captures the image
  • Saves it to storage

You don't see these internal steps.

You only use the feature.

That's abstraction.


Java Example

abstract class Animal {

    abstract void sound();

}

class Dog extends Animal {

    void sound() {
        System.out.println("Dog barks");
    }

}
Enter fullscreen mode Exit fullscreen mode

The Animal class says every animal must have a sound() method, but it doesn't specify how. Each subclass provides its own implementation.


Why is Abstraction Important?

Without abstraction, users would need to understand every internal detail before using software.

With abstraction:

  • Programs become easier to use.
  • Complex code is hidden.
  • Developers can change internal implementation without affecting users.
  • Applications become cleaner and more maintainable.

Comparing the Four Pillars

Pillar Simple Meaning Real-Life Example
Encapsulation Protect your data and control access ATM or Bank Account
Inheritance Reuse code from another class Child inheriting traits from parents
Polymorphism One method behaves differently Different animals making different sounds
Abstraction Hide complexity and show only what's needed Driving a car or using a smartphone

Quick Summary

Concept Meaning
OOP Programming using objects
Class Blueprint or template
Object Real instance created from a class
Properties Data about an object
Methods Actions performed by an object
Encapsulation Protect data
Inheritance Reuse existing code
Polymorphism Same method, different behavior
Abstraction Hide internal complexity

Top comments (0)