What are the four pillars of object-oriented programming, and how does Java realize each one in concrete language features?
answer
- Encapsulation = access modifiers + getters/setters
- Inheritance = extends (one class) + interfaces (many) + super
- Polymorphism = overriding + dynamic dispatch (runtime)
- Abstraction = abstract class (state + partial) vs interface (pure contract)
- Single inheritance of implementation, multiple of type; Object is the root
basics
~10 sThe four pillars are encapsulation, inheritance, polymorphism, and abstraction. Java uses access modifiers for encapsulation, extends and interfaces for inheritance, method overriding for polymorphism, and abstract classes and interfaces for abstraction.
solid answer
~40 sOOP rests on four pillars, and Java gives each a concrete mechanism. Encapsulation: bundle data with the methods that act on it and hide internals using access modifiers (private, protected, public, package-private) plus getter/setter conventions. Inheritance: a class reuses and extends another via extends (one class only) and gains type via interfaces; super reaches the parent, and you can override its methods. Polymorphism: one reference type can refer to many concrete types, and calls to overridden methods are resolved at runtime by dynamic dispatch (late binding). Abstraction: hide complexity behind abstract classes (partial implementation plus state) and interfaces (a pure contract). Java's signature choices are single inheritance of implementation but multiple inheritance of type through interfaces, and every class implicitly extending Object as the universal root.
go deeper
Can name the four pillars and point to the Java keyword for each (access modifiers, extends/implements, override, abstract/interface).
Explains dynamic dispatch as the runtime mechanism behind polymorphism, and distinguishes overloading from overriding correctly.
Articulates Java's 'single inheritance of implementation, multiple of type' design and why interfaces avoid the diamond problem; connects each pillar to concrete API design choices.
Frames the pillars as trade-offs (e.g. composition over inheritance, interface segregation) and reasons about how Java's choices shape large-scale module boundaries and evolvability.
## What OOP is **Object-oriented programming (OOP)** is a way of structuring software around **objects** — bundles of *data* (called **fields** or *state*) and *behavior* (called **methods** or *operations*) — instead of around standalone procedures. A **class** is the blueprint; an **object** (or *instance*) is a concrete thing built from that blueprint. The discipline is traditionally described by **four pillars**. Below each pillar is defined from scratch and then mapped to the exact Java feature that delivers it. ### 1. Encapsulation **Definition:** keeping an object's internal data together with the code that operates on it, and *hiding* the internals so outside code can only touch them through a controlled surface. The benefit is that you can change the internals later without breaking callers. **Java mechanism:** **access modifiers** placed on fields and methods: - `private` — visible only inside the same class. - *(no keyword)* **package-private** (the default) — visible to classes in the same package. - `protected` — visible in the same package *and* to subclasses. - `public` — visible everywhere. Convention: make fields `private` and expose `public` **getters/setters** (accessor methods) so reads and writes go through code you control. ### 2. Inheritance **Definition:** a new class (the **subclass** or *child*) reuses and specializes an existing class (the **superclass** or *parent*), inheriting its non-private members. This expresses an **IS-A** relationship (a `Dog` IS-A `Animal`). **Java mechanism:** the `extends` keyword. **Java allows extending only one class** (*single inheritance of implementation*) to avoid the ambiguity of inheriting conflicting implementations. The `super` keyword calls the parent constructor (`super(...)`) or a parent method (`super.foo()`). Every class that does not explicitly extend something implicitly extends **`java.lang.Object`**, the universal root of all classes. ### 3. Polymorphism **Definition:** "many forms" — one piece of code works with objects of many different concrete types through a common supertype. The classic form is *subtype polymorphism*: a variable of type `Animal` can hold a `Dog` or a `Cat`, and calling `speak()` runs the right version. **Java mechanism:** **method overriding** plus **dynamic method dispatch** (also called **late binding** or **runtime polymorphism**): when you call an overridden method, the JVM picks the implementation based on the object's *actual runtime type*, not the *declared* (compile-time) type of the reference. (Java also has *compile-time polymorphism* via **overloading**, where the compiler picks among same-named methods by their parameter lists — a separate, statically resolved mechanism.) ### 4. Abstraction **Definition:** exposing *what* something does while hiding *how* it does it — modeling the essential interface and suppressing detail. **Java mechanism:** two tools. An **abstract class** (`abstract class`) can declare **abstract methods** (no body, subclasses must implement) while also holding fields/state and concrete methods — a *partial* implementation that cannot itself be instantiated. An **interface** is a pure contract: historically only abstract method signatures and constants, now also `default` and `static` methods. A class `implements` an interface to promise it provides the behavior. ## Java's defining design choices - **Single inheritance of implementation, multiple inheritance of type:** a class extends at most one class but can `implements` *many* interfaces — you inherit one implementation hierarchy but any number of type contracts. This sidesteps the classic *diamond problem* of multiple implementation inheritance. - **`Object` as universal root:** every object gets `equals`, `hashCode`, `toString`, `getClass`, etc., for free. - **Everything (except primitives) is an object** reached through a **reference**. Understanding the pillars *as universal ideas* and then *as the specific Java keyword that realizes each* is exactly what this topic asks you to connect.
- Why does Java allow multiple inheritance of type (interfaces) but not of implementation (classes)?Multiple implementation inheritance creates the diamond problem: if two parents provide conflicting method bodies or state, the compiler can't decide which to inherit. Interfaces historically carried no implementation or state, so combining many caused no ambiguity. (Default methods reintroduced a limited diamond, which Java resolves with explicit override rules.)
- Which pillar does the @Override annotation relate to, and what does it do?Polymorphism via overriding. @Override is a compile-time check: it makes the compiler verify the method truly overrides a supertype method, catching typos in name or signature that would otherwise silently create a new, non-overriding method.
Think of a TV remote: the buttons (public interface) are all you touch — that's abstraction and encapsulation hiding the circuitry. A universal remote that works on any TV brand is polymorphism: one 'Power' button, many concrete TVs respond correctly.
saying these in an interview costs you the question
- Confusing overloading (compile-time, same name different params) with overriding (runtime, same signature in subclass) — they are different mechanisms.
- Saying Java supports multiple inheritance of classes — it does not; only of interfaces (type).
- Claiming abstraction and encapsulation are the same thing — encapsulation hides data, abstraction hides implementation complexity behind an interface.
- Forgetting that primitives (int, boolean...) are not objects and don't participate in the OOP hierarchy.