Why this matters
- Java gives you no choice: every line of code lives inside a class, so these ideas are the grammar of the language rather than an optional style.
- The four pillars are the vocabulary used in every design discussion and almost every interview, and loose definitions are immediately audible.
- The real payoff is maintenance. Code organised around objects changes in one place when a rule changes.
The problem it solves
Before object orientation, programs were procedures operating on shared data. Any procedure could modify any data, so a change to one field meant auditing every procedure that touched it. As programs grew, nobody could say with confidence what might break.
Object orientation inverts that. Data becomes private to a class, and only that class's methods may touch it. A change to a field is now confined to one file.
Class versus object
| Aspect | Class | Object |
|---|---|---|
| What it is | A template describing structure and behaviour | A concrete instance with its own values |
| When it exists | Written once, loaded once | Created at run time, many times |
| Lives in | Metaspace, as class metadata | The heap |
| Holds state | Only static fields, shared by all | Its own copy of every instance field |
| Count | One per declaration | As many as you construct |
What it is
ClassA template describing structure and behaviourObjectA concrete instance with its own valuesWhen it exists
ClassWritten once, loaded onceObjectCreated at run time, many timesLives in
ClassMetaspace, as class metadataObjectThe heapHolds state
ClassOnly static fields, shared by allObjectIts own copy of every instance fieldCount
ClassOne per declarationObjectAs many as you construct
One class, many objects. The class is the cookie cutter; the objects are the cookies.
public class Book {
private final String title; // each object gets its own
private int copiesAvailable;
private static int totalBooks; // one copy, shared by every object
public Book(String title, int copiesAvailable) {
this.title = title;
this.copiesAvailable = copiesAvailable;
totalBooks++;
}
public boolean borrow() {
if (copiesAvailable == 0) return false;
copiesAvailable--;
return true;
}
public static int totalBooks() {
return totalBooks;
}
}
Book java = new Book("Effective Java", 3);
Book clean = new Book("Clean Code", 1);
java.borrow();
System.out.println(Book.totalBooks()); // 2 — shared across both objects
Each Book has its own title and copiesAvailable. totalBooks belongs to the class, so both
constructors incremented the same counter.
The four pillars
What each one actually means
- Encapsulation — bundle data with the methods that operate on it, and keep the data private. The object enforces its own rules, so no caller can put it in an invalid state.
- Inheritance — define a class in terms of an existing one, reusing its behaviour and specialising what differs. In Java,
extendsfor classes andimplementsfor interfaces. - Polymorphism — one reference type, many run-time behaviours. A
Listvariable may be anArrayListor aLinkedList, and calling code does not change. - Abstraction — expose what a thing does and hide how it does it. Interfaces and abstract classes are the tools; a simple public method over complex internals is the everyday form.
The four pillars in one example
// Abstraction: callers depend on what a payment does, not how
public interface PaymentMethod {
boolean charge(BigDecimal amount);
}
// Encapsulation: balance is private and guarded by the class's own rules
public class Wallet implements PaymentMethod {
private BigDecimal balance;
public Wallet(BigDecimal balance) {
this.balance = balance;
}
@Override
public boolean charge(BigDecimal amount) {
if (balance.compareTo(amount) < 0) return false;
balance = balance.subtract(amount);
return true;
}
}
// Inheritance: a specialised wallet reusing everything above
public class RewardsWallet extends Wallet {
public RewardsWallet(BigDecimal balance) {
super(balance);
}
@Override
public boolean charge(BigDecimal amount) {
boolean ok = super.charge(amount);
if (ok) awardPoints(amount);
return ok;
}
private void awardPoints(BigDecimal amount) { }
}
// Polymorphism: this method never changes, whatever you pass it
public void checkout(PaymentMethod method, BigDecimal total) {
if (!method.charge(total)) {
throw new IllegalStateException("Payment declined");
}
}
Adding a new payment method means writing one class. The checkout method is never touched.
That is the entire value proposition in one line.
Associations between objects
Objects rarely stand alone. The relationship between two of them has a name, and the name tells you about lifetime.
- Association — a general "knows about" link. An
Orderholds a reference to aCustomer. - Aggregation — a "has a" link where the part survives independently. A
DepartmenthasEmployees, but deleting the department does not delete the people. - Composition — a "has a" link where the part cannot outlive the whole. A
HousehasRooms; destroy the house and the rooms are gone. The container usually creates the parts itself.
The practical test is whether the contained object makes sense on its own. If it does, you have aggregation; if it does not, composition. This distinction becomes concrete when you decide whether a constructor should accept a part or build it.
Common misreadings
- "Everything should be an object." Utility classes of static methods, like
MathorCollections, are legitimate and correct. Not every concept needs state. - "Inheritance is the main tool for reuse." Composition is usually the better one, for reasons covered in detail later in this module.
- "Encapsulation means writing a getter and setter for every field." A public setter for every private field is encapsulation in name only. Expose operations, not fields.
- "A class is an object." The class is the definition.
newproduces objects from it.
Quick recall
Everything you need if you only revisit this box.
- A class is a blueprint stored as metadata; an object is a heap instance with its own copy of each instance field.
staticmembers belong to the class. - Encapsulation hides data behind access modifiers so the object protects its own validity.
- Inheritance reuses and specialises an existing class.
- Polymorphism lets one reference type behave as several run-time types.
- Abstraction exposes a contract and hides the implementation.
- Encapsulation hides state; abstraction hides complexity. That is the distinction interviewers probe.
- Relationships differ by lifetime: aggregation parts survive the whole, composition parts do not.
Test yourself
Answer these before moving on — recall is what makes it stick.
- What are the four pillars of OOP (Encapsulation, Inheritance, Polymorphism, Abstraction)? Explain each with real-world examples.
- What are the four access modifiers in Java? Explain their scope with package and inheritance examples.
- Explain the diamond problem. How Java 8 resolved it with default methods?