OOP Interview Questions and Answers

OOP interview questions and oops interview questions appear in almost every software interview—from campus placements to senior system design loops. Panels want more than definitions: they expect you to explain encapsulation vs abstraction, defend composition over inheritance, walk through compile-time vs runtime polymorphism, and apply SOLID to a real class diagram. Java oops interview questions are especially common in India and enterprise hiring because Java remains the default teaching language for object-oriented design.

Below are 40+ OOP interview questions grouped by topic. Each response explains the concept and ends with a strong answer you can adapt in an interview. This guide is language-aware but emphasizes Java where interviewers drill syntax (abstract, interface, access modifiers). For JVM and Java-specific depth beyond OOP, continue with Java interview questions part 1 and part 2. For C++ OOP and memory, see C and C++ interview questions. For Python's object model and duck typing, see Python developer interviews.

NOTE
Prep tip: For each technical question, read What interviewers are testing aloud, then practice the full answer. Know the four pillars with examples, composition vs inheritance, overloading vs overriding, abstract class vs interface, all five SOLID letters, and one design pattern you have shipped—not textbook-only Singleton trivia. Use A strong answer is as your 20-second closing line in the interview.

Interview context and how to prepare

What OOP interviews actually test

OOP interviews test whether you can model problems as objects with clear responsibilities—not whether you can recite "four pillars" without context.

Layer What interviewers probe
Fundamentals Class, object, encapsulation, abstraction
Relationships Inheritance, composition, association
Polymorphism Overloading, overriding, dynamic dispatch
Java OOPs Access modifiers, abstract, interface, super
Design quality Coupling, cohesion, SOLID
Patterns Strategy, Factory, Observer, when to use
Scenarios Parking lot, notification system, payment module
Role Emphasis
Fresher / campus Pillars, overloading vs overriding, modifiers
Mid-level Composition, SOLID, one pattern with example
Senior / SDET LSP violations, DIP in frameworks, OOD whiteboard

Typical OOP interview loop

Round Duration Focus
Aptitude / screening 30 min Basics, four pillars, Java syntax
Technical — fundamentals 45–60 min Inheritance, polymorphism, abstract vs interface
Technical — design 45–60 min SOLID, patterns, composition
Live coding / OOD 45–60 min Class diagram, implement small hierarchy
Managerial 30 min Team practices, code review, refactoring stories

Experienced loops expect you to connect pillars, SOLID, and patterns to real class design—not recite definitions alone.

Realistic 3–5 week OOP prep plan

Week Focus Output
1 Four pillars + class diagrams Explain each with one example
2 Inheritance, composition, polymorphism Runnable Java demos
3 Abstract class vs interface, Java modifiers Cheat sheet you can draw
4 SOLID + 3 patterns One pattern per creational/behavioral
5 OOD scenarios + mock Whiteboard parking lot or library

Draw UML-style boxes on paper—interviewers reward clear entity relationships.


OOP vs procedural programming — what is the difference?

What interviewers are testing: Whether you can explain when procedural functions fit scripts and pipelines—and when object boundaries, encapsulation, and interfaces pay off as teams and domain rules grow.

Aspect Procedural Object-oriented
Unit of design Functions, procedures Classes and objects
State Often global or passed parameters Encapsulated in objects
Reuse Functions, modules, libraries, composition Classes, composition, interfaces, inheritance
Modeling Step-by-step algorithms Entities with behavior
Scaling teams Globals and side effects hurt Boundaries via classes and interfaces help in large OOP codebases

Procedural code is fine for scripts and small tools—see shell scripting interviews. Large systems can use procedural, functional, data-oriented, or hybrid design; OOP is one common choice when many developers share a long-lived codebase with changing requirements.

A strong answer is:

Procedural code organizes logic as functions with shared state; OOP bundles state and behavior in objects—I use procedural for scripts and OOP when many developers share an evolving domain model.

How does OOP differ across Java, Python, and C++?

What interviewers are testing: Whether you can contrast Java's class-and-interface model, Python's duck typing, and C++ lifetime semantics with concrete examples—not treat all three as identical OOP.

Feature Java Python C++
Model Class-based; single inheritance of classes, multiple interface implementation Class + duck typing Multiple inheritance allowed
Encapsulation private, protected, public Naming conventions (_name) and name mangling (__name); no Java-style private enforcement private, protected, public
Abstraction abstract class, interface ABC module, protocols (3.8+) Pure virtual classes
Polymorphism Overload + override Duck typing + override Virtual functions, templates
Memory/lifetime Garbage collection Automatic memory management / GC Deterministic lifetime via RAII; smart pointers, with manual control available

Java oops interview questions focus on modifiers and interfaces. Python interviews stress duck typing—see Python interviews. C++ adds multiple inheritance and vtables—see C and C++ interviews.

A strong answer is:

Java has single class inheritance plus interfaces and GC; Python relies heavily on dynamic/duck typing and conventions rather than enforced private access; C++ adds multiple inheritance and deterministic RAII-based lifetime management.


Four pillars and core concepts

What are the four pillars of OOP?

What interviewers are testing: Whether you understand the four concepts as different design tools, not four memorized definitions.

Pillar Meaning Example
Encapsulation Bundle data + methods; control access private balance + deposit()
Abstraction Expose what, hide how PaymentGateway.charge() hides PCI details
Inheritance Model an IS-A subtype relationship SavingsAccount extends Account
Polymorphism One interface, many behaviors Shape.draw() for Circle vs Square

The pillars work together: encapsulation protects state, abstraction simplifies usage, inheritance shares structure, polymorphism lets callers depend on supertypes.

A strong answer is:

I name all four and immediately ground each in code—private fields for encapsulation, an interface for abstraction, extends for inheritance, and overriding draw() for polymorphism.

What is the difference between a class and an object?

What interviewers are testing: Whether you distinguish a type definition from runtime instances and per-instance state.

Term Definition
Class Blueprint—fields, methods, constructors
Object Runtime instance created from a class
Instance Synonym for object in many interviews
java
class Dog {
    String name;
    void bark() { System.out.println("woof"); }
}

Dog rex = new Dog();  // rex is an object (instance) of class Dog

One class → many objects (new Dog() twice yields two instances with separate state).

A strong answer is:

A class is the template; an object is a concrete instance at runtime with its own field values—one Car class, many Car objects in a fleet.

What is encapsulation?

What interviewers are testing: Whether you protect invariants and implementation boundaries, not merely make every field private.

Encapsulation binds data and methods that operate on that data into one unit (usually a class) and restricts direct access to internal state.

Benefits:

  • Invariant protection — balance cannot go negative if withdraw validates
  • Refactoring freedom — change internal representation without breaking callers
  • Controlled access — callers cannot mutate implementation state directly
java
public class BankAccount {
    private int balance;

    public void deposit(int amount) {
        if (amount > 0) balance += amount;
    }

    public int getBalance() { return balance; }
}

A strong answer is:

Encapsulation keeps state private and exposes behavior through methods so invariants stay enforced—I never let callers set balance directly if rules matter.

What is abstraction?

What interviewers are testing: Whether you can expose a stable useful contract while hiding implementation choices.

Abstraction hides implementation complexity and shows only essential behavior—the "what" without the "how."

Mechanism Role
Abstract class Partial implementation + shared code
Interface Type contract—modern Java interfaces may contain default, static, and private helper methods
Public API Service method names hide database/HTTP details

Driving a car: you use accelerate()—not spark-plug timing. That is abstraction at the human level; in code, List lets callers program to list operations without depending on whether the concrete implementation is ArrayList, LinkedList, or another implementation.

A strong answer is:

Abstraction is the simplified surface—an interface or abstract API—so callers depend on capabilities like charge() without knowing Stripe vs PayPal wiring.

Encapsulation vs abstraction — what is the difference?

What interviewers are testing: Whether you can distinguish protecting internal state from simplifying what callers need to know.

Encapsulation Abstraction
Focus Protecting data Hiding complexity
Level Implementation (how data is guarded) Design (what you expose)
Mechanism private fields, getters Interfaces, abstract classes
Question answered "Who can touch this state?" "What can this thing do?"

You can encapsulate without strong abstraction (public getters for everything). You can abstract without strict encapsulation (leaky interface returning internals).

A strong answer is:

Encapsulation guards state with access control; abstraction hides how work is done behind a simpler contract—I need both, but they answer different design questions.

What is data hiding and how does it relate to encapsulation?

What interviewers are testing: Whether you understand that visibility control is one mechanism used by encapsulation, not a synonym for it.

Data hiding restricts unnecessary visibility of implementation details, commonly with private or package-scoped access and, where inheritance genuinely requires it, protected.

Concept Scope
Encapsulation Broader—bundling data + behavior
Data hiding Narrower—visibility of fields

Encapsulation can exist with public fields (weak hiding). Production code should hide data and expose behavior.

A strong answer is:

Data hiding is the access-modifier part of encapsulation—I use private fields so internal representation can change without breaking every caller.

What is inheritance?

What interviewers are testing: Whether you use inheritance for true substitutable subtype relationships, rather than code reuse alone.

Inheritance creates a subtype relationship in which a child class derives behavior and state from a parent and can be used where that parent type is expected—an IS-A relationship.

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

class Dog extends Animal {
    void bark() { System.out.println("woof"); }
}

Shared implementation is a benefit, but inheritance should model a valid IS-A/substitution relationship rather than being chosen only to avoid duplicate code. Risks: tight coupling, fragile base class, deep trees—often replaced by composition for HAS-A.

A strong answer is:

Inheritance models IS-A reuse and enables overriding; I avoid deep trees and prefer composition when behavior is shared but not a true subtype relationship.

What is polymorphism?

What interviewers are testing: Whether you can program to a supertype/interface and let implementations vary without changing callers.

Polymorphism ("many forms") lets one interface or superclass reference invoke different implementations depending on the actual object type.

Interview terminology often calls method overloading "compile-time/static polymorphism," although subtype polymorphism specifically refers to substitutable implementations and dynamic dispatch.

Two forms in Java:

Type Mechanism Binding
Compile-time Method overloading Static
Runtime Method overriding Dynamic
java
interface Notifier {
    String send(String message);
}

class EmailNotifier implements Notifier {
    public String send(String message) { return "email:" + message; }
}

class SmsNotifier implements Notifier {
    public String send(String message) { return "sms:" + message; }
}

public class PolymorphismDemo {
    static String notifyUser(Notifier n, String msg) {
        return n.send(msg);
    }

    public static void main(String[] args) {
        System.out.println(notifyUser(new EmailNotifier(), "hello"));
        System.out.println(notifyUser(new SmsNotifier(), "hello"));
    }
}
Output

The same notifyUser method accepts any Notifier; runtime dispatch picks email: vs sms: output.

A strong answer is:

Polymorphism lets callers depend on a common supertype while different implementations provide behavior at runtime. In Java interviews, method overloading is also commonly called compile-time polymorphism, while overriding gives true runtime dispatch.


Inheritance, composition, and relationships

What are the types of inheritance?

What interviewers are testing: Whether you know Java's class-inheritance limitation and how interfaces provide multiple type inheritance.

Type Structure Example
Single One parent Dog extends Animal
Multilevel Chain GoldenRetriever extends Dog extends Animal
Hierarchical Many children, one parent Cat, Dog extend Animal
Multiple Several parents C++ yes; Java classes no
Hybrid Combination Mix of hierarchical + multiple (via interfaces in Java)

Java classes: single inheritance of classes, multiple interface implementation.

A strong answer is:

Java gives single class inheritance and multiple interfaces—I describe multilevel and hierarchical with Animal examples and mention C++ for true multiple inheritance contrast.

Composition vs inheritance — when do you choose each?

What interviewers are testing: Whether you can recognize when HAS-A delegation creates safer flexibility than IS-A coupling.

Inheritance (IS-A) Composition (HAS-A)
Relationship Subtype Contains / uses
Coupling Tight to parent Looser—swap parts
Flexibility Fixed at compile hierarchy Inject strategies at runtime
Risk Fragile base class Slightly more boilerplate
java
interface Engine {
    String start();
}

final class PetrolEngine implements Engine {
    public String start() { return "vroom"; }
}

final class Car {
    private final Engine engine;

    Car(Engine engine) {
        this.engine = engine;
    }

    String drive() {
        return engine.start();
    }
}

public class CompositionDemo {
    public static void main(String[] args) {
        System.out.println(new Car(new PetrolEngine()).drive());
    }
}
Output

Favor composition when behavior varies or lifetime is HAS-A. Use inheritance for genuine taxonomic subtyping and shared interface contracts.

A strong answer is:

I default to composition for reusable behavior—Car has Engine—and reserve inheritance for true IS-A subtypes where Liskov substitution holds.

Aggregation vs composition vs association?

What interviewers are testing: Whether you understand the relationships as different ownership/lifetime semantics in the domain model.

Relationship Ownership Lifetime
Association Uses Independent
Aggregation Weak HAS-A Part can outlive whole
Composition Strong HAS-A Part dies with whole

Example: Doctor associated with Patient; Team aggregates Player objects that can exist independently; House composes Room objects as parts of that modeled house.

Java does not mechanically enforce UML "part dies with whole" lifecycle rules—composition here is a domain-model ownership concept.

A strong answer is:

Composition is strict ownership in the domain model—house and its rooms; aggregation is looser—team and players who can exist independently; association is mere usage—doctor and patient.

IS-A vs HAS-A — explain with examples.

What interviewers are testing: Whether you can spot an inheritance relationship that fails behavioral substitutability.

Relation Keyword in design Example
Subtype relation extends / implements ElectricCar subtype of Car
HAS-A Field reference Car HAS-A Engine

Interview trap: modeling Stack extends ArrayList IS-A wrong for behavior—Stack HAS-A list (composition) avoids LSP violations.

A strong answer is:

IS-A for subtype polymorphism; HAS-A when one object contains or uses another—I rejected Stack extends ArrayList because a stack is not an array list behaviorally.

What is the diamond problem in multiple inheritance?

What interviewers are testing: Whether you understand ambiguity caused by multiple inherited implementations and Java's resolution rules.

When class D inherits B and C, and both B and C inherit A and override the same method, D faces ambiguous which override to use:

text
A
   / \
  B   C
   \ /
    D

Java does not support multiple inheritance of classes, so this form of multiple-base-class ambiguity cannot occur through class extension. Interfaces can still inherit conflicting default methods; Java requires the implementing class to resolve such conflicts explicitly. C++ allows multiple class inheritance and addresses ambiguity with mechanisms such as virtual inheritance.

A strong answer is:

Java avoids class-extension diamond ambiguity by allowing only one superclass—I use interfaces and override explicitly when default methods conflict.

How does Java achieve multiple inheritance without extending two classes?

What interviewers are testing: Whether you know Java supports multiple interfaces/types but only one superclass.

A class may:

java
class PaymentService implements Auditable, Retryable, MetricsAware { }

Interfaces define contracts; a class implements many. Since Java 8, default methods on interfaces share implementation—but conflicting defaults require an override in the class.

A strong answer is:

Java gives multiple inheritance of type through interfaces, not multiple class extension—default methods add shared code with explicit conflict rules.

Method overloading vs method overriding?

What interviewers are testing: Whether you understand compile-time overload selection vs runtime override dispatch.

Overloading Overriding
Same name Yes, different parameters Same name and parameter types; compatible/covariant return type
Class Same class (or inherited) Parent-child
Polymorphism Compile-time (static) Runtime (dynamic)
Return type Can differ if params differ Covariant returns allowed
Access Any Cannot reduce visibility
java
class Calc {
    int add(int a, int b) { return a + b; }
    double add(double a, double b) { return a + b; }  // overload
}

class Parent { String greet() { return "hi"; } }
class Child extends Parent {
    @Override String greet() { return "hello"; }     // override
}

A strong answer is:

Overloading is same method name, different parameters, resolved at compile time; overriding is subclass replacing parent behavior, resolved at runtime via dynamic dispatch.


Polymorphism, abstraction, and Java types

What is compile-time (static) polymorphism?

What interviewers are testing: Whether you understand how Java chooses an overloaded signature from compile-time types.

Achieved through method overloading. C++ supports user-defined operator overloading; Java does not allow user-defined operator overloads (though + has predefined behavior for numbers and strings).

The compiler resolves the overloaded method using the compile-time types of the receiver and arguments, plus Java's overload-resolution rules:

java
class Printer {
    void print(int x) { System.out.println("int:" + x); }
    void print(String s) { System.out.println("str:" + s); }
}

public class StaticPoly {
    public static void main(String[] args) {
        Printer p = new Printer();
        p.print(42);
        p.print("hi");
    }
}
Output

Running prints int:42 then str:hi—the compiler bound each call statically.

A strong answer is:

Compile-time or static polymorphism is the common interview term for method overloading: the compiler selects the applicable method from compile-time argument types. Java does not support user-defined operator overloading like C++.

What is runtime (dynamic) polymorphism?

What interviewers are testing: Whether you understand dynamic dispatch based on the runtime object's overridden method.

Achieved through method overriding: reference type is superclass/interface; actual object type decides which method runs.

For overridable instance methods, Java uses runtime dynamic dispatch based on the actual object type. JVM implementations optimize this using techniques such as method tables, inline caches, and JIT devirtualization. final, static, and private methods do not participate in runtime override dispatch the same way.

A strong answer is:

Runtime polymorphism is overriding—a variable typed as Animal holding a Dog calls Dog's speak() at runtime because dispatch uses the object's actual class.

What are upcasting and downcasting?

What interviewers are testing: Whether you can use supertypes normally and recognize that frequent downcasting often signals weak abstraction.

Cast Direction Safety
Upcasting Child → parent Implicit, always safe
Downcasting Parent → child Explicit, can fail
java
Animal a = new Dog();           // upcast (implicit)
Dog d = (Dog) a;                // downcast — ClassCastException if wrong
if (a instanceof Dog dog) {     // Java 16+ pattern matching
    dog.bark();
}

Prefer polymorphism so downcasting is unnecessary. When the runtime type is genuinely uncertain, use instanceof / pattern matching before accessing subtype-specific behavior.

A strong answer is:

Upcast to general types for polymorphism; downcast only when needed and after instanceof—or better, redesign with polymorphism so the cast disappears.

What is an abstract class?

What interviewers are testing: Whether you know when a shared base needs state/implementation plus extension points.

An abstract class cannot be instantiated; it may contain abstract methods (no body) and concrete methods.

java
abstract class Shape {
    abstract double area();
    void label() { System.out.println("shape"); }
}

Use when subtypes share common state or implementation but need specialized behavior.

A strong answer is:

Abstract classes are partial blueprints—I share code and fields in Shape while forcing Circle to implement area().

What is an interface?

What interviewers are testing: Whether you understand interfaces as contracts/capabilities decoupled from a concrete implementation.

An interface defines a type contract. Its abstract methods must be implemented by a concrete class unless inherited implementation satisfies them; modern interfaces may also provide default, static, and private helper methods. Fields declared in an interface are implicitly public static final constants.

java
interface Persistable {
    void save();
    void delete();
    default void archive() { save(); }
}

class User implements Persistable {
    public void save() { /* ... */ }
    public void delete() { /* ... */ }
}

Implementors do not need to implement default methods unless they override them. A class may implement multiple interfaces.

A strong answer is:

Interfaces define what a type can do without dictating inheritance tree—I implement several on one service class for cross-cutting contracts.

Abstract class vs interface — when do you use each?

What interviewers are testing: Whether you choose between shared base implementation and multiple capability contracts.

Factor Abstract class Interface
Instantiation No No
Multiple inherit One class only Many interfaces
State Can have instance fields Fields are public static final only
Constructors Yes No
Evolution New concrete methods are generally compatible; new abstract methods require subclass changes New abstract methods break implementers; default methods can evolve contracts compatibly
Use when Shared code + IS-A base Capability contract

Java 8+ blurs the line with default methods—still prefer interface for roles, abstract class for shared base implementation.

A strong answer is:

Interface for capabilities (Comparable, Runnable); abstract class when subclasses share fields and helper methods—I don't use abstract class just to block instantiation; use private constructor instead.


Java OOPs specifics

Explain Java access modifiers.

What interviewers are testing: Whether you understand Java visibility rules—including protected access across packages—not just a four-column cheat sheet.

Modifier Class Package Subclass access World
private Yes No No No
(default) Yes Yes No No
protected Yes Yes Yes No
public Yes Yes Yes Yes

This table is a simplification; cross-package protected access has additional rules.

Interview tip: Across packages, protected access is available to subclasses through the inherited/subclass context; it is not equivalent to general package-wide access to arbitrary superclass instances. Prefer private + public methods when possible.

A strong answer is:

I default to private fields, public behavior methods, and protected only when subclasses genuinely need hooks—package-private for internal module APIs.

What does final mean for class, method, and variable?

What interviewers are testing: Whether you understand what final prevents—and what it doesn't make immutable.

Use Effect
final class Cannot be extended
final method Cannot be overridden
final variable May be assigned once; a final reference cannot point to another object, but the referenced object may still be mutable

String being final prevents subclasses from changing its observable behavior, which helps preserve the guarantees callers rely on. Use final on method parameters and local variables when values should not be reassigned (readability).

A strong answer is:

final prevents reassignment, not mutation of the referenced object. It helps build immutable types when combined with immutable state.

Static vs instance members in OOP?

What interviewers are testing: Whether you distinguish object-specific behavior from class-level state/utility and understand global-state trade-offs.

Instance Static
Belongs to Each object Class
Access Needs object (or this) Class name
Override Yes (polymorphism) No—hiding only
Use Per-object state Constants, factories, counters

Static methods cannot access instance fields directly. Overuse of static hurts testability and OOP boundaries—see also Java part 1 static questions.

A strong answer is:

Instance members carry per-object state; static belongs to the class—I avoid static mutable state because it breaks encapsulation and makes tests order-dependent.

What constructor rules and patterns should you know in Java?

What interviewers are testing: Whether you know constructor generation/chaining and superclass initialization, not a memorized list of constructor types.

Concept Meaning
Compiler-provided default constructor Generated only when the class declares no constructor
Explicit no-arg constructor Developer-written zero-parameter constructor
Parameterized constructor Accepts initialization values
Copy-style constructor User-defined convention; Java has no built-in copy constructor feature
Constructor chaining One constructor invokes another with this(...) or a superclass constructor with super(...)

If any constructor is defined, the compiler does not auto-generate a default. If a superclass has no accessible no-argument constructor, the subclass constructor must ultimately invoke an accessible superclass constructor with the required arguments.

A strong answer is:

I use parameterized constructors for required fields and add an explicit no-arg constructor only when frameworks need it—remembering Java removes the compiler default once I define any constructor, and that subclass constructors must reach a valid superclass constructor.

What are this and super in Java?

What interviewers are testing: Whether you understand current-instance access, superclass access, and constructor chaining rules—including modern flexible constructor bodies.

Keyword Refers to Common use
this Current object Field disambiguation, this() chaining
super Parent class super() constructor, super.method()
java
class Employee extends Person {
    Employee(String name, int id) {
        super(name);
        this.id = id;
    }
}

this refers to the current object; super accesses superclass members or invokes a superclass constructor. Traditionally Java required explicit this(...)/super(...) as the first statement, but Java 25's flexible constructor bodies allow safe statements before that invocation as long as they do not improperly use the object before superclass construction.

A strong answer is:

this refers to the current instance and super to the superclass. I use them for field disambiguation, method access, and constructor chaining; in modern Java, safe validation or computation may occur before an explicit super(...) or this(...) call.

What are default methods on interfaces (Java 8+)?

What interviewers are testing: Whether you understand how default methods let interfaces evolve without breaking every implementor.

java
interface Logger {
    void log(String msg);
    default void logInfo(String msg) { log("INFO: " + msg); }
}

Allows evolving interfaces without breaking every implementor—implementors inherit default unless they override.

Conflict rule: if two interfaces provide the same default, the class must override and choose.

A strong answer is:

Default methods let me add behavior to interfaces without forcing every implementor to update—if two defaults clash, I override explicitly in the class.


Coupling, cohesion, and SOLID

What are coupling and cohesion?

What interviewers are testing: Whether you can recognize boundaries that make change and testing local instead of cascading.

Metric Good Bad
Cohesion Class does one focused job God class does everything
Coupling Classes depend on abstractions Classes reach into each other's internals

High cohesion + low coupling = easier tests and refactors. OOP tools: interfaces, composition, package-private boundaries.

A strong answer is:

I want high cohesion inside a class and loose coupling between classes—depending on PaymentGateway interface, not StripeClient concrete type.

What are the SOLID principles?

What interviewers are testing: Whether you can use SOLID as design heuristics on real code, rather than expand five acronyms.

Letter Principle One line
S Single Responsibility One reason to change
O Open/Closed Open for extension, closed for modification
L Liskov Substitution Subtypes must work wherever parent worked
I Interface Segregation Small interfaces
D Dependency Inversion Depend on abstractions

SOLID guides maintainable OOP—common in mid/senior loops and Spring Boot design discussions.

A strong answer is:

SOLID is a set of design heuristics: keep responsibilities focused, extend behavior without repeatedly modifying stable code, preserve subtype contracts, keep interfaces narrow, and make high-level logic depend on abstractions. I use them to reduce change impact, not as rigid rules.

Explain Single Responsibility Principle (SRP).

What interviewers are testing: Whether you can identify different reasons for change hidden inside one class.

A class should have only one reason to change—one axis of responsibility.

Bad: Invoice generates PDF, sends email, and calculates tax.
Better: Invoice, PdfRenderer, Mailer, TaxCalculator collaborate.

SRP improves testability—mock mailer without touching tax math.

A strong answer is:

SRP means one job per class—if email templates and tax rules change for different reasons, they belong in different classes, not one InvoiceGod.

Explain Open/Closed Principle (OCP).

What interviewers are testing: Whether changing requirements can be handled through extension instead of repeatedly editing stable branching logic.

Software entities should be open for extension, closed for modification—add behavior without editing stable code.

Pattern: Strategy — new DiscountStrategy class instead of editing checkout() switch:

java
interface DiscountStrategy { int apply(int total); }
class TenPercent implements DiscountStrategy {
    public int apply(int total) { return total * 90 / 100; }
}

A strong answer is:

OCP means I extend with new strategy or handler classes instead of patching a growing if-else in the core checkout method every time marketing adds a promo.

Explain Liskov Substitution Principle (LSP).

What interviewers are testing: Whether a subtype preserves the behavioral contract expected by callers.

A subtype violates LSP if code written for the base type behaves incorrectly or unexpectedly when given the subtype. At a more formal level, that can mean strengthened preconditions, weakened postconditions, or other broken behavioral expectations.

Classic illustration: Square extends Rectangle—setting width should not break square invariants if callers expect independent width and height semantics.

java
// Anti-pattern: Square changes independent width/height semantics
class Square extends Rectangle {
    void setWidth(int w) { super.setWidth(w); super.setHeight(w); }
}

Callers expecting Rectangle behavior get surprises—favor composition over forced inheritance.

A strong answer is:

LSP means subtypes must preserve the behavioral contract callers rely on—Square-as-Rectangle violates that, so I model Square independently or use composition.

Explain Interface Segregation and Dependency Inversion.

What interviewers are testing: Whether you keep contracts narrow and make high-level policy independent of concrete infrastructure.

ISP: Clients should not depend on methods they do not use.

java
// Bad: force read-only repo to implement delete()
interface Repository { void save(); void delete(); }

// Better: split
interface Writer { void save(); }
interface Deleter { void delete(); }

DIP: High-level modules depend on abstractions, not concretions.

java
class OrderService {
    private final PaymentGateway gateway; // interface
    OrderService(PaymentGateway gateway) { this.gateway = gateway; }
}

Dependency injection frameworks such as Spring make DIP easier to implement by wiring abstractions to concrete implementations—see Spring Boot interviews.

A strong answer is:

ISP splits fat interfaces so implementors aren't forced to stub unused methods; DIP injects PaymentGateway interfaces into services so tests swap fakes without changing OrderService.


Design patterns and object-oriented design

Explain creational patterns: Singleton, Factory, Builder.

What interviewers are testing: Whether you can choose a creation pattern because of a real creation problem, rather than name patterns from memory.

Pattern Purpose Interview caution
Singleton One instance Hidden global state; prefer DI
Factory / Simple Factory Centralize object creation and hide concrete classes Decouples caller from concrete class
Builder Construct an object step-by-step, especially with many optional values HttpRequest.Builder, custom User.Builder, Lombok @Builder
java
interface Notification { void send(); }
class NotificationFactory {
    static Notification create(String type) {
        return switch (type) {
            case "email" -> new EmailNotification();
            default -> new SmsNotification();
        };
    }
}

A strong answer is:

Factory hides concrete types; Builder assembles complex objects; Singleton only when one instance is truly required—I prefer Spring-scoped beans over hand-rolled Singletons.

Explain Strategy and Observer patterns.

What interviewers are testing: Whether you can distinguish interchangeable behavior from event publication/subscription.

Strategy: Encapsulate interchangeable algorithms—payment methods, compression codecs.

Observer: One-to-many notification—UI listeners, domain events.

java
interface PayStrategy { void pay(int cents); }

final class Checkout {
    private final PayStrategy strategy;

    Checkout(PayStrategy strategy) {
        this.strategy = strategy;
    }

    void checkout(int cents) {
        strategy.pay(cents);
    }
}

Strategy supports OCP—add CryptoPay without editing Checkout internals.

A strong answer is:

Strategy encapsulates interchangeable algorithms behind one interface—Checkout can be configured with Visa, UPI, or another payment strategy without changing Checkout itself; Observer decouples event publishers from subscribers like order-placed emails.

Explain Adapter and Decorator patterns.

What interviewers are testing: Whether you know the difference between changing an interface and layering behavior.

Pattern Role Example
Adapter Wrap incompatible API to match expected interface Legacy LegacyPaymentPaymentGateway
Decorator Add behavior without subclass explosion BufferedInputStream wrapping FileInputStream

Decorator avoids subclassing every combination of features; Adapter integrates third-party libraries into your OOP boundaries.

A strong answer is:

Adapter makes legacy APIs fit my interface; Decorator layers behavior—Java I/O streams are the textbook Decorator example I cite in interviews.

How would you design a parking lot system using OOP?

What interviewers are testing: Whether you can whiteboard entities, responsibilities, and patterns for a classic OOD prompt without a god class.

Entities (interview whiteboard approach):

Class Responsibility
ParkingLot Floors, entry/exit, availability
ParkingFloor Spots collection
ParkingSpot Size, occupied, vehicle
Vehicle Car, Truck, Motorcycle (type enum or subclass)
Ticket Entry time, spot id
PricingStrategy Interface — hourly, flat

Use composition: lot HAS floors HAS spots. Use Strategy for pricing. Avoid one ParkingLotManager God class doing payment + SMS + spot math.

A strong answer is:

I identify entities and responsibilities first, use composition for lot/floor/spot ownership, Strategy for pricing, and separate allocation/payment concerns so no single ParkingLot service becomes a god object.

What are common OOP anti-patterns?

What interviewers are testing: Whether you can identify design symptoms and explain an appropriate refactoring direction without applying patterns mechanically.

Anti-pattern Problem
God object One class knows everything
Anemic domain model Can be problematic when a genuinely rich domain's business rules are scattered across services; not automatically wrong for simple CRUD/data-transfer models
Deep inheritance Fragile overrides
Yo-yo problem Jump many levels for one method
Premature pattern Factory for one implementation

Refactor toward small cohesive classes and composition.

A strong answer is:

God classes and deep inheritance hierarchies are red flags—I split responsibilities and inject strategies instead of adding another override layer.

OOP vs functional programming — how do they compare?

What interviewers are testing: Whether you understand that real systems often combine object boundaries with functional transformation styles.

OOP emphasis Functional emphasis
Encapsulate state and behavior behind object boundaries Prefer transformations expressed as functions
Identity and lifecycle can be important Immutability and referential transparency are often emphasized
Dynamic dispatch/interfaces provide extensibility Higher-order functions and function composition provide extensibility
Mutable state is possible but should be controlled Side effects are commonly isolated

Modern Java routinely mixes the two styles—stream().map().filter() is functional style on collections while domain models remain OOP.

A strong answer is:

I use OOP for domain entities with lifecycle and functional style for transformations on immutable data—Java streams don't mean I abandon encapsulation in core models.

What is the difference between a value object and an entity?

What interviewers are testing: Whether you distinguish identity-based entities from value-based objects in domain modeling.

Entity Value object
Identity Distinguished by ID even if attributes change Defined by its values
Equality Same ID → same entity Same field values → equal
Mutability Often mutable lifecycle Often immutable
Examples Customer with customerId Money, DateRange; Address when identity does not matter in the domain

Whether something is a value object depends on domain semantics—an address could have identity in some systems. Value objects simplify invariants when defined by values: two Money(10, "USD") instances with the same amount and currency are interchangeable. Entities track continuity over time—a Customer keeps identity after an address change.

A strong answer is:

Entities have identity that persists through change; value objects are compared by value and are often immutable—I'd model Money as a value object and Order as an entity with an order ID.


Final-week OOP interview checklist

Use the final week to rehearse explanations and scenarios—not to memorize every definition.

  • Four pillars with one example each
  • Encapsulation vs abstraction and data hiding
  • Overloading vs overriding + compile vs runtime polymorphism
  • Composition vs inheritance + IS-A vs HAS-A
  • Abstract class vs interface decision tree
  • Diamond problem and Java interface default-method resolution
  • Access modifiers table
  • SOLID — all five with examples
  • Two patterns — Strategy + Factory/Simple Factory or Observer
  • One OOD scenario — parking lot or library
  • Java part 1 for Java-only follow-ups
  • C and C++ if systems role

Pattern cheat sheet (quick reference)

Need OOP approach
Hide state Encapsulation + private fields
Hide complexity Abstraction / interface
Reuse IS-A behavior Inheritance (carefully)
Reuse HAS-A behavior Composition
Swap algorithms Strategy pattern
Create objects without new everywhere Factory
Many optional features Decorator or composition
Notify many listeners Observer
One class, one job SRP
Extend without editing core OCP + Strategy
Safe subtyping LSP
Testable wiring DIP + interfaces

References

Official Java documentation


Summary

OOP interviews test whether you can explain why encapsulation and polymorphism matter, when composition beats inheritance, and how SOLID shows up in real code—not recite four pillar names from memory. Use this guide as a self-test: answer aloud and run the polymorphism and composition demos. Pair with Java interviews for language follow-ups and C and C++ interviews when memory and multiple inheritance come up.

Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)