By WebNest Studio Engineering Team
Java - Core Tutorial
OOPs Concepts in Java
Object-Oriented Programming (OOP) is a way of designing software around "objects" — self-contained units that bundle data (fields) with the behavior (methods) that operates on that data. Java was built as an object-oriented language from the ground up, so almost everything you write, aside from the eight primitive types, is an object or a reference to one.
The motivation behind OOP is managing complexity. Procedural code tends to scatter data and the functions that act on it across a program, which becomes hard to maintain as the codebase grows. OOP keeps related data and behavior together inside classes, which makes large systems easier to reason about, extend, and test in isolation.
Why it matters
The four pillars are not exam vocabulary; they are the reasons large Java codebases stay manageable. Encapsulation keeps invalid data out, abstraction hides detail you do not need, inheritance removes duplication, and polymorphism lets new types slot in without changing existing code. Almost every Java interview opens with a question about them.
Watch: Java OOPs Concepts: The Overall View
Prefer to watch? This video gives a big-picture overview of object-oriented programming in Java: classes, objects and the four pillars.
The Four Pillars of OOP
Every object-oriented feature in Java ultimately supports one of four core principles. Understanding these four ideas up front makes every later topic in this module — classes, inheritance, overriding, and initializer blocks — click into place faster.
- Encapsulation — bundling data and the methods that operate on it inside a class, and restricting direct access to that data using access modifiers (typically
privatefields withpublicgetters/setters). This protects an object's internal state from invalid changes. - Inheritance — allowing one class (a subclass) to acquire the fields and methods of another class (a superclass) using the
extendskeyword, enabling code reuse and a natural "is-a" relationship between types. - Polymorphism — allowing the same method call to behave differently depending on the actual object it is invoked on (runtime/dynamic polymorphism via overriding) or depending on the arguments passed (compile-time polymorphism via overloading).
- Abstraction — hiding internal implementation details and exposing only the essential features of an object, typically through abstract classes and interfaces, so callers depend on "what" an object does, not "how" it does it.
Object and Class as the Foundation
All four pillars are built on top of two foundational concepts: a class, which is a blueprint describing what fields and methods a category of objects will have, and an object, which is an actual instance created from that blueprint at runtime, occupying its own memory on the heap. Nothing else in OOP makes sense without this class/object distinction, which is why it is the very next topic.
OOP vs Procedural Programming
In procedural programming, a program is a sequence of functions that pass data around. In object-oriented programming, a program is a set of objects that each look after their own data and talk to each other through methods. The difference shows up as a program grows.
- Organisation — procedural code groups by steps; OOP groups by things (a
Customer, anOrder, aPayment), each with its own data and methods. - Data safety — procedural data is often shared and changed from anywhere; OOP keeps fields
privateand changes them only through methods that can validate input. - Reuse — procedural code reuses functions; OOP also reuses whole types through inheritance and composition.
- Change — adding a new kind of thing in OOP usually means adding a new class, not editing every function that handles the old kinds.
How the Four Pillars Work Together
The pillars are rarely used one at a time. In the second example below, Shape is abstract, so callers only know that every shape has an area (abstraction). Its name field is private and read through a getter (encapsulation). Circle and Rectangle extend Shape and reuse its name handling (inheritance). Finally, the loop calls shape.area() on each element of a Shape[] array, and Java runs the right version for each object at runtime (polymorphism). Adding a Triangle later would mean writing one new class; the loop would not change.
Why Java Enforces OOP Structure
Unlike some multi-paradigm languages, Java requires almost all code to live inside a class — there are no free-floating functions outside a class the way there are in C or Python. This is a deliberate design decision: it forces every piece of behavior to have an owner (a class), which keeps large codebases organized and makes dependencies explicit rather than implicit.
Examples
A tiny class demonstrating encapsulation and abstraction together
public class BankAccount {
private double balance; // encapsulated: not directly accessible from outside
public BankAccount(double initialBalance) {
balance = initialBalance;
}
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
public double getBalance() { // controlled access to private data
return balance;
}
public static void main(String[] args) {
BankAccount account = new BankAccount(500.0);
account.deposit(150.0);
System.out.println("Balance: " + account.getBalance());
}
}
Balance: 650.0
All four pillars in one program: abstraction, encapsulation, inheritance and polymorphism
public class ShapeDemo {
public static void main(String[] args) {
Shape[] shapes = { new Circle(2), new Rectangle(3, 4) };
for (Shape shape : shapes) {
// Polymorphism: the same call runs Circle's or Rectangle's area()
System.out.printf("%s area: %.2f%n", shape.getName(), shape.area());
}
}
}
// Abstraction: callers know every Shape has an area, not how it is calculated
abstract class Shape {
private final String name; // Encapsulation: private, read through a getter
Shape(String name) {
this.name = name;
}
String getName() {
return name;
}
abstract double area();
}
// Inheritance: Circle and Rectangle reuse Shape's name handling
class Circle extends Shape {
private final double radius;
Circle(double radius) {
super("Circle");
this.radius = radius;
}
@Override
double area() {
return Math.PI * radius * radius;
}
}
class Rectangle extends Shape {
private final double width;
private final double height;
Rectangle(double width, double height) {
super("Rectangle");
this.width = width;
this.height = height;
}
@Override
double area() {
return width * height;
}
}
Circle area: 12.57
Rectangle area: 12.00
Common Mistakes
- Treating OOP as just "using classes" — without encapsulation, inheritance, polymorphism, and abstraction actually being applied, a class-based program is not meaningfully object-oriented.
- Confusing overloading (compile-time polymorphism) with overriding (runtime polymorphism) as if they were the same mechanism.
- Making every field public instead of private, which defeats encapsulation and allows any code to corrupt an object's internal state.
Exercise
Write a Thermostat that protects its own data. The target temperature must stay between 16 and 30; a request outside that range is ignored.
Expected output: 22, then 22 again after an attempt to set it to 40.
class Thermostat {
// TODO: a private field for the target temperature, starting at 20
// TODO: setTarget(int value) that ignores values below 16 or above 30
// TODO: getTarget()
}
public class ThermostatDemo {
public static void main(String[] args) {
Thermostat thermostat = new Thermostat();
thermostat.setTarget(22);
System.out.println(thermostat.getTarget());
thermostat.setTarget(40);
System.out.println(thermostat.getTarget());
}
}
Show hints
- Make the field
privateso the only way to change it is throughsetTarget. - Inside the setter, assign the value only when it is within the allowed range.
Show solution
class Thermostat {
private int target = 20;
void setTarget(int value) {
if (value >= 16 && value <= 30) {
target = value;
}
}
int getTarget() {
return target;
}
}
public class ThermostatDemo {
public static void main(String[] args) {
Thermostat thermostat = new Thermostat();
thermostat.setTarget(22);
System.out.println(thermostat.getTarget()); // 22
thermostat.setTarget(40);
System.out.println(thermostat.getTarget()); // 22
}
}
Quick quiz
1. Keeping fields private and exposing them only through methods that enforce rules is an example of which principle?
- A. Inheritance
- B. Polymorphism
- C. Encapsulation
- D. Overloading
Show answer
C. Encapsulation bundles data with the methods that control it and hides the data from outside code.
2. The same call, shape.area(), runs different code depending on whether the object is a Circle or a Square. Which principle is this?
- A. Encapsulation
- B. Abstraction
- C. Aggregation
- D. Polymorphism
Show answer
D. Polymorphism means one interface with many implementations, chosen by the actual type of the object at runtime.
3. What is the relationship between a class and an object?
- A. A class is a blueprint; an object is an instance created from it
- B. They are the same thing
- C. An object is a blueprint for a class
- D. A class is stored on the heap, an object on the stack
Show answer
A. A class defines fields and methods. Each object created with new is a separate instance with its own field values.
Interview questions
What are the four pillars of object-oriented programming?
Show answer
Encapsulation: keeping data and the methods that operate on it together and restricting direct access. Abstraction: exposing what an object does while hiding how. Inheritance: a class reusing and extending the fields and methods of another. Polymorphism: one method call behaving differently depending on the object's actual type.
What is the difference between abstraction and encapsulation?
Show answer
Abstraction is about design: deciding what to expose so callers can use something without knowing its internals, typically through abstract classes and interfaces. Encapsulation is about implementation: hiding the data inside a class with access modifiers and controlling it through methods. Abstraction hides complexity; encapsulation hides and protects state.
Key Points to Remember
- The four pillars of OOP are encapsulation, inheritance, polymorphism, and abstraction.
- A class is a blueprint; an object is a runtime instance created from that blueprint.
- Java requires almost all code to live inside a class, enforcing object-oriented structure by design.
- The pillars work together: an abstract type, private state, subclasses and one polymorphic call site is the typical shape of OOP code.
Practice in the playground
Write and run your own code for this topic, or start from the exercise or an example. Runs plain Java 17. Frameworks such as Spring, and databases, are not available here. Your code for each topic is kept in this browser.
Run the examples
Change an input, predict the result, then compare it with the output. Explain why the result changes.
Written by
WebNest Studio Engineering Team
Practical lessons from developers working with Java, Python, React, databases and production systems.
Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering