OOP

Practice commonly asked OOP interview questions with clear answers and explanations.

30 Interview Questions

OOP Interview Questions

30 Questions
Q 1

Why should inheritance be designed for extension or else prohibited using 'final' (Effective Java Item 19)?

Hard
Answer
Subclassing an un-designed class exposes internal implementation details (fragile base class problem). If a class is not specifically documented and designed with safe hooks for extension, it should be marked 'final' to prevent hazardous subclassing.
Explanation
Overriding a method in a subclass might inadvertently break other internal methods in the superclass that rely on private assumptions.
Code Example Java
// Prohibiting unsafe subclassing by making class final:
public final class SecureTokenGenerator {
    public String generateToken() {
        return UUID.randomUUID().toString();
    }
}
Reference: Java OOP Concepts
Q 2

What is the Prototype Design Pattern and how does it create objects without constructor invocation?

Medium
Answer
The Prototype pattern creates new objects by cloning an existing configured prototype instance rather than constructing fresh objects from scratch, avoiding expensive initialization or database lookups.
Explanation
It is preferred when object creation cost is high (e.g. reading configuration from network or parsing large files).
Code Example Java
interface Prototype<T> { T clonePrototype(); }
class GamePiece implements Prototype<GamePiece> {
    private String color;
    public GamePiece(String color) { this.color = color; }
    public GamePiece clonePrototype() { return new GamePiece(this.color); }
}
Reference: Java OOP Concepts
Q 3

What is the Flyweight Design Pattern and how does it optimize memory in Java?

Hard
Answer
The Flyweight pattern minimizes memory usage by sharing common, immutable state (intrinsic state) across many fine-grained objects, passing distinct context-specific data (extrinsic state) to methods at runtime.
Explanation
Java's String Constant Pool and Integer.valueOf() caching mechanism (-128 to 127) are canonical examples of the Flyweight pattern.
Code Example Java
public class IntegerCacheDemo {
    public static void main(String[] args) {
        Integer a = Integer.valueOf(100);
        Integer b = Integer.valueOf(100);
        System.out.println(a == b); // True (Flyweight cache shares same object instance!)
    }
}
Reference: Java OOP Concepts
Q 4

What is the difference between State Pattern and Strategy Pattern in Java?

Hard
Answer
While both share similar UML structures (delegating to an interface), their intent differs: Strategy pattern allows clients to choose different algorithms externally. State pattern allows an object to alter its internal behavior automatically when its internal state changes.
Explanation
In State pattern, state transitions are typically handled by concrete state classes changing the context's current state pointer.
Code Example Java
interface State { void handle(); }
class PlayingState implements State { public void handle() { System.out.println("Playing video..."); } }
class PausedState implements State { public void handle() { System.out.println("Video paused."); } }
class MediaPlayer {
    private State state = new PausedState();
    public void setState(State s) { this.state = s; }
    public void pressPlay() { state.handle(); }
}
Reference: Java OOP Concepts
Q 5

What is the Command Design Pattern and how does it decouple invoker from receiver?

Hard
Answer
The Command pattern encapsulates a request as an object with all its parameters, decoupling the object that invokes the command from the object that knows how to perform it. It enables undo/redo, queuing, and logging of operations.
Explanation
Runnable and Callable interfaces in Java are classic functional representations of the Command pattern.
Code Example Java
interface Command { void execute(); }
class Light { void turnOn() { System.out.println("Light on"); } }
class LightOnCommand implements Command {
    private final Light light;
    public LightOnCommand(Light l) { this.light = l; }
    public void execute() { light.turnOn(); }
}
// Invoker holds command
class RemoteControl { private Command slot; public void setCommand(Command c) { this.slot = c; } public void pressButton() { slot.execute(); } }
Reference: Java OOP Concepts
Q 6

How does the Facade Design Pattern simplify complex subsystems in OOP?

Easy
Answer
The Facade pattern provides a simplified, higher-level unified interface to a complex subsystem of classes, reducing coupling between client code and internal subsystem components.
Explanation
Clients interact only with the Facade class rather than coordinating dozens of low-level subsystem classes directly.
Code Example Java
class DvdPlayer { void on() {} }
class Projector { void on() {} }
class HomeTheaterFacade {
    private DvdPlayer dvd = new DvdPlayer();
    private Projector proj = new Projector();
    public void watchMovie() {
        dvd.on();
        proj.on();
        System.out.println("Movie started");
    }
}
Reference: Java OOP Concepts
Q 7

What is the Proxy Design Pattern and how is Dynamic Proxy used in Java frameworks?

Hard
Answer
The Proxy pattern provides a surrogate or placeholder object to control access to a target object (for lazy loading, caching, logging, or security). Java's Dynamic Proxy (java.lang.reflect.Proxy) generates proxy classes at runtime for interfaces.
Explanation
Spring AOP and Hibernate Lazy Loading rely heavily on Dynamic Proxies and CGLIB bytecode enhancement.
Code Example Java
interface Service { void execute(); }
class RealService implements Service { public void execute() { System.out.println("Execution"); } }
class ServiceProxy implements Service {
    private RealService realService;
    public void execute() {
        System.out.println("Security check");
        if (realService == null) realService = new RealService(); // Lazy loading
        realService.execute();
    }
}
Reference: Java OOP Concepts
Q 8

What is an Adapter Design Pattern and how does it bridge incompatible interfaces?

Medium
Answer
The Adapter pattern converts the interface of a class into another interface that clients expect, allowing classes with incompatible interfaces to work together through composition or inheritance.
Explanation
Arrays.asList() and InputStreamReader (adapting byte stream to character stream) are standard JDK examples of the Adapter pattern.
Code Example Java
interface ModernSocket { void plugIn5V(); }
class Legacy110VSocket { void supply110V() { System.out.println("110V output"); } }

// Adapter bridges Legacy to Modern interface
class SocketAdapter implements ModernSocket {
    private final Legacy110VSocket legacySocket;
    public SocketAdapter(Legacy110VSocket socket) { this.legacySocket = socket; }
    public void plugIn5V() { legacySocket.supply110V(); System.out.println("Converted to 5V"); }
}
Reference: Java OOP Concepts
Q 9

What is the Null Object Design Pattern in Java OOP?

Medium
Answer
The Null Object pattern replaces null references with a concrete object that implements the target interface with neutral, default, or do-nothing behavior, eliminating repetitive NullPointerException checks.
Explanation
It is an OOP alternative to returning null or wrapping return values in Optional when neutral behavior is appropriate.
Code Example Java
interface Logger { void log(String msg); }
class ConsoleLogger implements Logger { public void log(String m) { System.out.println(m); } }
class NullLogger implements Logger { public void log(String m) { /* Do nothing safely */ } }

class App {
    private Logger logger = new NullLogger(); // Guaranteed non-null default
    public void setLogger(Logger logger) { this.logger = logger != null ? logger : new NullLogger(); }
}
Reference: Java OOP Concepts
Q 10

What is the difference between Open-Recursion and Direct Invocation in OOP method overriding?

Hard
Answer
Open-Recursion (Dynamic Dispatch) means that when a superclass method invokes another method within itself using 'this.method()', Java dynamically invokes the overridden subclass version at runtime, rather than the superclass version.
Explanation
Invoking overridable methods inside a constructor can lead to subtle bugs because subclass fields are not yet initialized when the parent constructor runs.
Code Example Java
class Parent {
    Parent() { print(); } // Dangerous: Calls overridden method before Child is initialized!
    void print() { System.out.println("Parent"); }
}
class Child extends Parent {
    int value = 42;
    @Override
    void print() { System.out.println("Child value: " + value); }
}
// new Child() prints: Child value: 0 (value uninitialized during super constructor)
Reference: Java OOP Concepts
Q 11

What is Method Chaining and Fluent Interface design in Java OOP?

Easy
Answer
Method Chaining is an OOP syntax pattern where each method returns the current object reference (return this;), allowing multiple method invocations to be chained consecutively on a single line.
Explanation
Fluent interfaces improve code readability and are widely used in Builder patterns, Stream APIs, and query builders.
Code Example Java
public class QueryBuilder {
    private StringBuilder query = new StringBuilder();
    public QueryBuilder select(String fields) { query.append("SELECT ").append(fields); return this; }
    public QueryBuilder from(String table) { query.append(" FROM ").append(table); return this; }
    public String build() { return query.toString(); }
}
// Usage:
String sql = new QueryBuilder().select("*").from("users").build();
Reference: Java OOP Concepts
Q 12

What is the Dependency Injection (DI) Pattern and what are its three primary types in Java?

Medium
Answer
Dependency Injection is a technique where an object receives its dependencies from an external source rather than creating them internally using 'new'. The three main types are Constructor Injection (preferred), Setter Injection, and Field Injection.
Explanation
Constructor injection is favored because it enables immutability (final fields) and guarantees objects cannot be instantiated in an incomplete state.
Code Example Java
class PaymentProcessor {
    private final PaymentGateway gateway; // Immutability supported
    // Constructor Injection:
    public PaymentProcessor(PaymentGateway gateway) {
        this.gateway = Objects.requireNonNull(gateway);
    }
}
Reference: Java OOP Concepts
Q 13

What are the limitations of Java's Cloneable interface and how is it fixed using Copy Factories?

Hard
Answer
Cloneable is a flawed marker interface because clone() is declared protected in Object and does not invoke constructors, bypassing initialization safeguards. Static Copy Factories or Copy Constructors are preferred as they work smoothly with final fields and avoid type casts.
Explanation
Joshua Bloch (Effective Java) explicitly advises using copy constructors or static copy factory methods instead of Cloneable.
Code Example Java
public class UserProfile {
    private final String username;
    public UserProfile(String username) { this.username = username; }
    // Copy Factory Method:
    public static UserProfile newInstance(UserProfile original) {
        return new UserProfile(original.username);
    }
}
Reference: Java OOP Concepts
Q 14

What is the difference between Interface Inheritance (extends) and Implementation Inheritance (implements)?

Easy
Answer
Interface inheritance (interface extends interface) defines a subtype contract hierarchy without sharing state. Implementation inheritance (class implements interface or class extends class) binds concrete executable behavior and memory structure.
Explanation
An interface can extend multiple interfaces simultaneously (e.g. interface Deque extends Queue).
Code Example Java
interface Collection {}
interface List extends Collection {} // Interface inheritance
class ArrayList implements List {}    // Implementation inheritance
Reference: Java OOP Concepts
Q 15

Why is 'instanceof' considered a code smell when overused in OOP design?

Medium
Answer
Overusing 'instanceof' with cascading if-else blocks violates the Open/Closed Principle (OCP) and bypasses Polymorphism, forcing callers to know about concrete subclasses instead of delegating behavior dynamically.
Explanation
Instead of checking 'if (obj instanceof Circle)', declare an abstract draw() method on Shape and let polymorphic dispatch handle execution.
Code Example Java
// Bad (Code Smell):
// if (shape instanceof Circle) drawCircle(); else if (shape instanceof Square) drawSquare();

// Good OOP Polymorphism:
interface Shape { void draw(); }
void render(Shape shape) { shape.draw(); }
Reference: Java OOP Concepts
Q 16

What is Object-Oriented Domain-Driven Design (DDD) Entity vs Value Object?

Hard
Answer
An Entity has a distinct identity (e.g. ID field) that runs continuously throughout its lifecycle even if attributes change. A Value Object has no distinct identity and is defined entirely by its attribute values (immutable, compared by value equality).
Explanation
In modern Java, Value Objects are best modeled using Record classes (e.g. Money, Address, GeoCoordinates).
Code Example Java
// Value Object (Compared by value equality):
public record Money(BigDecimal amount, String currency) {}

// Entity (Identified by unique ID):
class Customer {
    private final UUID id;
    private String name;
    public Customer(UUID id, String name) { this.id = id; this.name = name; }
}
Reference: Java OOP Concepts
Q 17

What is the Liskov Substitution Principle (LSP) and how does it prevent flawed inheritance hierarchies?

Hard
Answer
LSP states that subtypes must be substitutable for their base types without altering program correctness. Subclasses must not strengthen preconditions (accept narrower inputs) or weaken postconditions (guarantee less output) than their parent.
Explanation
Classic violation: An Ostrich extending Bird and throwing UnsupportedOperationException on fly() breaks client expectations that all Birds can fly.
Code Example Java
// LSP Compliant hierarchy:
interface Bird {}
interface FlyingBird extends Bird { void fly(); }

class Sparrow implements FlyingBird { public void fly() {} }
class Ostrich implements Bird {} // Does not implement FlyingBird (Avoids LSP violation)
Reference: Java OOP Concepts
Q 18

Can an abstract class implement an interface without implementing all its methods?

Easy
Answer
Yes. An abstract class is not required to provide implementations for interface methods. Unimplemented interface methods are treated as abstract methods that must be implemented by the first concrete subclass.
Explanation
This pattern is known as the Skeletal Implementation (Abstract Adapter) pattern (e.g., AbstractList implementing List in the JDK).
Code Example Java
interface Repository {
    void save();
    void delete();
}
abstract class BaseRepository implements Repository {
    // Provides common implementation for save(), leaves delete() abstract
    public void save() { System.out.println("Entity saved"); }
    // delete() is left abstract for concrete subclasses
}
Reference: Java OOP Concepts
Q 19

What is the difference between Polymorphism and Duck Typing?

Hard
Answer
Java uses Nominal Polymorphism (type compatibility is explicitly declared via class inheritance and interface implementation contracts verified at compile time). Duck typing is dynamic polymorphism in dynamically typed languages where an object's suitability is determined by method presence rather than formal type hierarchy.
Explanation
In Java, an object cannot be passed where an interface is expected unless the class explicitly implements that interface, even if it has identical method signatures.
Code Example Java
interface Walker { void walk(); }
class Person implements Walker { public void walk() { System.out.println("Walking"); } }
// In Java, only instances explicitly implementing Walker can be passed:
void makeWalk(Walker w) { w.walk(); }
Reference: Java OOP Concepts
Q 20

What is Cohesion and Coupling in OOP software architecture?

Medium
Answer
Cohesion measures how focused and single-purposed a class's internal responsibilities are (High Cohesion is desired). Coupling measures the degree of direct dependency between separate classes (Low Coupling is desired).
Explanation
High cohesion and low coupling produce modular, maintainable, and easily testable code bases.
Code Example Java
// High Cohesion: Class only calculates tax
class TaxCalculator {
    public double calculateVat(double amount) { return amount * 0.20; }
}
// Low Coupling: Injected via Interface
class InvoiceService {
    private final TaxCalculator calculator;
    public InvoiceService(TaxCalculator calc) { this.calculator = calc; }
}
Reference: Java OOP Concepts
Q 21

Why is multiple inheritance of state prohibited in Java, but multiple inheritance of type allowed via interfaces?

Medium
Answer
Multiple inheritance of state (fields) causes memory layout conflicts and structural ambiguity (the Diamond Problem) when two parent classes contain identically named state fields. Multiple inheritance of type via interfaces is safe because interfaces are stateless and cannot hold instance variables.
Explanation
Interface default methods allow multiple behavioral inheritance, but Java resolves method conflicts by forcing implementing classes to explicitly override conflicting methods.
Code Example Java
interface Printable { void print(); }
interface Showable { void show(); }
// Safe multiple inheritance of type:
class Document implements Printable, Showable {
    public void print() { System.out.println("Print"); }
    public void show() { System.out.println("Show"); }
}
Reference: Java OOP Concepts
Q 22

What is the difference between 'this()' and 'super()' constructor calls?

Easy
Answer
this() invokes another overloaded constructor within the same class, whereas super() invokes a constructor of the direct parent superclass. Both must be the very first statement inside a constructor body.
Explanation
Because both must be the first line of a constructor, a constructor cannot contain both this() and super() simultaneously.
Code Example Java
class Parent {
    Parent(String msg) { System.out.println(msg); }
}
class Child extends Parent {
    Child() { this("Hello"); } // Calls overloaded Child(String)
    Child(String msg) { super(msg); } // Calls Parent(String)
}
Reference: Java OOP Concepts
Q 23

Can we overload or override constructors in Java?

Easy
Answer
Constructors CAN be overloaded (multiple constructors with different parameter lists in the same class), but they CANNOT be overridden because constructors are not inherited by subclasses.
Explanation
Subclasses invoke parent constructors using super(), but they cannot override them because a subclass constructor must have the name of the subclass, not the superclass.
Code Example Java
class Account {
    Account() { System.out.println("Default"); }
    Account(String type) { System.out.println("Type: " + type); } // Overloaded
}
class SavingsAccount extends Account {
    SavingsAccount() {
        super("Savings"); // Invokes parent constructor, not overriding it
    }
}
Reference: Java OOP Concepts
Q 24

What happens if a constructor is declared 'private' in Java?

Easy
Answer
A private constructor prevents direct instantiation of the class from outside and stops other classes from extending it via inheritance. It is used in Utility classes, Singleton patterns, and Factory-driven classes.
Explanation
Declaring a private constructor in a class with static methods (like java.lang.Math or Collections) signals that the class is purely a utility and should never be instantiated.
Code Example Java
public class StringUtils {
    // Private constructor prevents instantiation & subclassing
    private StringUtils() {
        throw new UnsupportedOperationException("Utility class");
    }
    public static boolean isEmpty(String s) { return s == null || s.isEmpty(); }
}
Reference: Java OOP Concepts
Q 25

What is the difference between Aggregation, Composition, and Association?

Medium
Answer
Association is a general relationship between two classes. Aggregation is a weak 'HAS-A' relationship where child objects have an independent lifecycle (e.g. Bank and Employee). Composition is a strong 'HAS-A' relationship where child objects cannot exist without the parent lifecycle (e.g. Order and OrderLineItem).
Explanation
In Composition, deleting the parent cascade-deletes the children. In Aggregation, deleting the aggregate parent leaves child instances intact in memory.
Code Example Java
// Aggregation: Employee survives if Department is deleted
class Employee {}
class Department { private List<Employee> employees; }

// Composition: LineItem dies if Order is deleted
class Order {
    private final List<LineItem> items = new ArrayList<>();
    class LineItem {}
}
Reference: Java OOP Concepts
Q 26

What is Polymorphic Arguments in Java method design?

Easy
Answer
Polymorphic Arguments refers to designing methods that accept superclass or interface reference types as parameters, allowing caller code to pass any subclass or implementing instance interchangeably.
Explanation
Designing with polymorphic arguments maximizes code reusability, follows the Liskov Substitution Principle, and decouples calling logic from concrete implementations.
Code Example Java
interface Shape { void draw(); }
class Renderer {
    // Polymorphic argument accepts Circle, Square, Triangle, etc.
    public void render(Shape shape) {
        shape.draw(); // Calls specific overridden draw() method
    }
}
Reference: Java OOP Concepts
Q 27

What is the difference between Static Block and Instance Initialization Block (IIB) in Java classes?

Medium
Answer
A static block executes once when the class is loaded into memory by the JVM. An instance initialization block (IIB) executes every time a new object instance is created, immediately before constructor execution.
Explanation
Execution sequence: Static Block (once on class load) -> Instance Initializer Block -> Constructor.
Code Example Java
class Demo {
    static { System.out.println("1. Static Block"); }
    { System.out.println("2. Instance Block"); }
    Demo() { System.out.println("3. Constructor"); }
}
Reference: Java OOP Concepts
Q 28

How does Variable Shadowing and Variable Hiding differ in Java OOP?

Medium
Answer
Variable Shadowing occurs when a local variable or method parameter has the same name as an instance variable in the same class. Variable Hiding occurs when a subclass declares a field with the same name as a field in its superclass.
Explanation
Shadowed variables are accessed via 'this.fieldName'. Hidden fields in parent classes are resolved based on the reference type, not polymorphic dispatch.
Code Example Java
class Parent { String name = "Parent"; }
class Child extends Parent {
    String name = "Child"; // Hides Parent.name
}
Parent p = new Child();
System.out.println(p.name); // Prints: Parent (Fields are not polymorphic!)
Reference: Java OOP Concepts
Q 29

Why is the instanceof operator combined with Record deconstruction (Java 21+) powerful for OOP data extraction?

Hard
Answer
Record Patterns (Java 21+) allow deconstructing record instances directly inside instanceof checks or switch expressions, extracting component values into variables without explicit getter calls.
Explanation
This feature provides seamless decomposition of immutable data aggregates in modern pattern-matching Java code.
Code Example Java
record Point(int x, int y) {}

Object obj = new Point(10, 20);
// Record Pattern matching deconstruction:
if (obj instanceof Point(int x, int y)) {
    System.out.println("Coordinates: " + x + ", " + y);
}
Reference: Java OOP Concepts
Q 30

What is the difference between Upcasting and Downcasting in Java inheritance?

Medium
Answer
Upcasting is casting a subclass object to a superclass reference (implicit, type-safe, always allowed). Downcasting is casting a superclass reference back to a subclass type (explicit, unsafe, throws ClassCastException if the object is not an instance of the target subtype).
Explanation
Always check compatibility with 'instanceof' before performing downcasting to avoid ClassCastException at runtime.
Code Example Java
class Animal {}
class Dog extends Animal { void bark() {} }

Animal a = new Dog(); // Upcasting (Implicit)
if (a instanceof Dog d) { // Safe Downcasting
    d.bark();
}
Reference: Java OOP Concepts

About This Topic

Prepare for OOP interviews with important concepts and commonly asked questions.