Skip to content
Java oop basics 6 min read

OOP Concepts

Object-Oriented Programming (OOP) is the design philosophy that Java was built around — instead of writing a long list of instructions, you model your program as a collection of objects that know things (data) and can do things (behavior). Once it clicks, it transforms how you think about every program you write.

Why OOP?

Before OOP, most programs were written procedurally — a sequence of functions acting on shared data. That approach works fine for small programs, but it falls apart fast as projects grow: data gets modified from anywhere, dependencies become tangled, and adding a feature risks breaking something else.

OOP solves this by bundling data and the code that operates on it into a single unit called a class. Think of a class as a blueprint and an object as a real thing built from that blueprint — just like a house plan versus the actual house.

Here is the simplest possible Java object in action:

public class Dog {
    String name;   // data (field)
    int age;

    void bark() { // behavior (method)
        System.out.println(name + " says: Woof!");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog d = new Dog();   // create an object from the blueprint
        d.name = "Rex";
        d.age  = 3;
        d.bark();
    }
}

Output:

Rex says: Woof!

The Four Pillars of OOP

Java’s OOP model rests on four pillars. Master these and you understand the language’s design at a fundamental level.

1. Encapsulation

Encapsulation means hiding the internal details of an object and exposing only what the outside world needs. You achieve this in Java by marking fields private and providing public getter/setter methods.

public class BankAccount {
    private double balance;  // hidden from outside

    public double getBalance() {
        return balance;
    }

    public void deposit(double amount) {
        if (amount > 0) balance += amount;  // validation lives here
    }
}

Because nothing outside BankAccount can touch balance directly, you control exactly how it changes. See Encapsulation for the full treatment, and Access Modifiers for the private/protected/public rules.

2. Inheritance

Inheritance lets one class reuse and extend the fields and methods of another. The existing class is the superclass (parent) and the new class is the subclass (child).

public class Animal {
    String name;

    public void eat() {
        System.out.println(name + " is eating.");
    }
}

public class Cat extends Animal {
    public void purr() {
        System.out.println(name + " is purring.");
    }
}

public class Main {
    public static void main(String[] args) {
        Cat c = new Cat();
        c.name = "Whiskers";
        c.eat();   // inherited from Animal
        c.purr();  // defined in Cat
    }
}

Output:

Whiskers is eating.
Whiskers is purring.

Cat gets eat() for free — you wrote it once in Animal. Explore this further at Inheritance and Types of Inheritance.

Note: Java supports single inheritance for classes (one parent only) but allows a class to implement multiple interfaces, giving you the flexibility of multiple inheritance without the diamond-problem ambiguity.

3. Polymorphism

Polymorphism means “many forms” — the same method name can behave differently depending on the object it is called on. Java supports two kinds:

KindWhen resolvedMechanism
Compile-time (static)At compile timeMethod overloading
Runtime (dynamic)At runtimeMethod overriding + reference type
public class Shape {
    public void draw() {
        System.out.println("Drawing a shape");
    }
}

public class Circle extends Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a circle");
    }
}

public class Main {
    public static void main(String[] args) {
        Shape s = new Circle();  // Shape reference, Circle object
        s.draw();                // runtime decides: Circle.draw()
    }
}

Output:

Drawing a circle

The magic is that s is declared as Shape, but the JVM calls Circle’s version at runtime — that is dynamic dispatch. Dive deeper at Polymorphism, Method Overloading, and Method Overriding.

4. Abstraction

Abstraction means showing only what is relevant and hiding the complexity. A TV remote is a perfect analogy: you press “Volume Up” without caring about the electronics inside.

In Java, you achieve abstraction through abstract classes and interfaces.

public abstract class Vehicle {
    abstract void startEngine();  // subclasses must implement this

    public void stop() {          // shared behavior already implemented
        System.out.println("Vehicle stopped.");
    }
}

public class Car extends Vehicle {
    @Override
    public void startEngine() {
        System.out.println("Car engine started with a key.");
    }
}

The caller only needs to know startEngine() exists — not how it works for each vehicle type.

OOP vs Procedural: A Quick Comparison

AspectProceduralObject-Oriented
FocusFunctions/proceduresObjects
DataShared, globalEncapsulated inside objects
ReuseCopy-paste or function callsInheritance & composition
MaintainabilityGets harder at scaleStays manageable
Example languagesC, PascalJava, C++, Python

Under the Hood

When you write Dog d = new Dog(), Java does several things at the JVM level:

  1. Class loading — the ClassLoader reads Dog.class from the classpath and loads the bytecode into the method area of the JVM.
  2. Memory allocationnew triggers the JVM to allocate space on the heap for the Dog object. Fields get default values (null for String, 0 for int).
  3. Constructor call — the constructor runs to initialize the object.
  4. Reference storage — the variable d on the stack holds a reference (essentially a pointer) to the heap object, not the object itself.

This reference-based model is why assigning Dog d2 = d gives you two variables pointing to the same object — changing d2.name also changes what you see through d. For the same reason, Java passes object references by value (see Call by Value).

Virtual method calls (the heart of runtime polymorphism) are implemented through a vtable — a per-class table of method pointers. When you call s.draw() on a Shape reference, the JVM looks up the vtable of the actual object (Circle) and dispatches to the right method. Learn more at vtable & Dynamic Dispatch.

Tip: Understanding heap vs stack and reference semantics will save you hours of debugging subtle bugs — especially when objects are passed to methods or stored in collections.

In This Section

These pages cover the foundational building blocks you need before moving on to inheritance and polymorphism:

  • Naming Conventions — the Java community’s agreed rules for naming classes, methods, variables, and constants so your code is immediately readable.
  • Classes & Objects — how to define a class, create objects with new, and understand the relationship between the two.
  • Methods — how to declare and call methods, pass arguments, return values, and understand method signatures.
  • Constructors — special methods that initialize objects when they are created, including constructor chaining and overloading.
  • static Keyword — how static fields and methods belong to the class itself rather than any individual object.
  • this Keyword — how this refers to the current object instance inside a method or constructor.
  • Object vs Class — clarifying the difference between a class (blueprint) and an object (instance), with practical examples.
  • Inheritance — extend classes to build an “IS-A” relationship and reuse code cleanly.
  • Polymorphism — write flexible code that works with objects of many related types.
  • Encapsulation — protect your data by hiding fields and controlling access through methods.
  • Abstract Class — define partial implementations that subclasses are required to complete.
  • Interfaces — define contracts that any class can implement, enabling powerful abstraction.
  • vtable & Dynamic Dispatch — understand exactly how the JVM resolves method calls at runtime.
Last updated June 13, 2026
Was this helpful?