OOP Interview Questions
Object-Oriented Programming (OOP) is one of the most tested topics in Java interviews, from junior roles all the way to senior engineers. This page walks through the most commonly asked OOP questions with honest, accurate answers and short code examples you can reason about out loud.
Fundamentals
Q1: What are the four pillars of OOP?
Every Java OOP interview starts here. The four pillars are:
| Pillar | What it means in Java |
|---|---|
| Encapsulation | Bundling data and methods; hiding state with private + getters/setters |
| Inheritance | A subclass extends a parent class and reuses its members |
| Polymorphism | One interface, many behaviors — method overloading and overriding |
| Abstraction | Exposing only what’s needed via abstract classes or interfaces |
Tip: Interviewers love follow-up questions on each pillar. Be ready to give a real example for each.
Q2: What is the difference between a class and an object?
A class is a blueprint — it defines fields, methods, and constructors but uses no memory on its own. An object is a concrete instance of that blueprint, living in heap memory.
class Car {
String model;
int year;
}
// object created at runtime
Car myCar = new Car();
myCar.model = "Tesla";
myCar.year = 2024;
See Classes & Objects for a deeper look.
Q3: What is encapsulation and why does it matter?
Encapsulation means keeping a class’s internal state private and exposing it only through controlled methods. This prevents accidental corruption of data and makes the class easier to maintain.
class BankAccount {
private double balance; // hidden
public double getBalance() { return balance; }
public void deposit(double amount) {
if (amount > 0) balance += amount;
}
}
The balance field cannot be set to a negative value from outside — the deposit method enforces the rule.
Inheritance
Q4: What is inheritance? What keyword does Java use?
Inheritance lets one class acquire the fields and methods of another using the extends keyword. It models an IS-A relationship.
class Animal {
void breathe() { System.out.println("Breathing..."); }
}
class Dog extends Animal {
void bark() { System.out.println("Woof!"); }
}
Dog d = new Dog();
d.breathe(); // inherited
d.bark(); // own method
Note: Java supports only single inheritance for classes. A class can extend exactly one other class.
Q5: Does Java support multiple inheritance? How do you work around it?
Java does not allow a class to extend more than one class (to avoid the Diamond Problem). However, a class can implement multiple interfaces, effectively achieving multiple-type inheritance.
interface Flyable { void fly(); }
interface Swimmable { void swim(); }
class Duck implements Flyable, Swimmable {
public void fly() { System.out.println("Duck flying"); }
public void swim() { System.out.println("Duck swimming"); }
}
See Types of Inheritance for the full picture.
Q6: What is the Diamond Problem?
The Diamond Problem occurs when a class inherits from two classes that both inherit from the same parent, creating ambiguity about which version of a method to use. Java sidesteps this for classes by disallowing multiple class inheritance. With interfaces, Java 8+ default methods can trigger a similar ambiguity — the class must explicitly override the conflicting method.
interface A { default void hello() { System.out.println("A"); } }
interface B extends A { default void hello() { System.out.println("B"); } }
interface C extends A { default void hello() { System.out.println("C"); } }
class D implements B, C {
// must override — compiler forces your hand
public void hello() { B.super.hello(); }
}
Q7: What does super do?
The super keyword refers to the immediate parent class. You use it to:
- Call the parent constructor:
super(args) - Call an overridden method:
super.methodName() - Access a shadowed field:
super.fieldName
class Vehicle {
Vehicle(String type) { System.out.println("Vehicle: " + type); }
}
class Car extends Vehicle {
Car() {
super("Car"); // must be first statement
System.out.println("Car created");
}
}
Output:
Vehicle: Car
Car created
Polymorphism
Q8: What is polymorphism? Name the two types.
Polymorphism means “many forms” — the same method name behaves differently depending on the context.
- Compile-time polymorphism — resolved at compile time via method overloading
- Runtime polymorphism — resolved at runtime via method overriding
Q9: What is the difference between method overloading and method overriding?
| Overloading | Overriding | |
|---|---|---|
| Where | Same class | Subclass |
| Signature | Different parameter list | Same signature |
| Return type | Can differ | Must be same (or covariant) |
| Binding | Compile-time (static) | Runtime (dynamic) |
@Override | Not applicable | Recommended |
// Overloading
class MathUtils {
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }
}
// Overriding
class Animal { void sound() { System.out.println("..."); } }
class Cat extends Animal {
@Override
public void sound() { System.out.println("Meow"); }
}
Q10: What is dynamic method dispatch?
Dynamic method dispatch is how Java achieves runtime polymorphism. When a parent reference holds a child object, the JVM looks up the actual type at runtime and calls the overriding version of the method — not the one declared in the reference type.
Animal a = new Cat(); // parent ref, child object
a.sound(); // prints "Meow", not "..."
Internally, the JVM uses a vtable (virtual method table) per class to resolve this at runtime. See vtable & Dynamic Dispatch for details.
Q11: Can you override a static method?
No. Static methods belong to the class, not the object. If you declare the same static method in a subclass, it is called method hiding, not overriding. The reference type decides which version runs — not the object type.
class Parent { static void greet() { System.out.println("Parent"); } }
class Child extends Parent { static void greet() { System.out.println("Child"); } }
Parent p = new Child();
p.greet(); // prints "Parent" — static binding!
Abstraction
Q12: What is an abstract class? When would you use one?
An abstract class cannot be instantiated. It can have a mix of abstract methods (no body) and concrete methods (with body). Use one when:
- You want to share code among closely related classes
- You need constructors or instance state in the base type
- You want to enforce that subclasses implement certain methods
abstract class Shape {
String color;
abstract double area(); // must override
void describe() { // shared behavior
System.out.println("I am a " + color + " shape");
}
}
class Circle extends Shape {
double radius;
Circle(double r) { this.radius = r; this.color = "red"; }
@Override
double area() { return Math.PI * radius * radius; }
}
Q13: What is an interface? How does it differ from an abstract class?
An interface defines a pure contract — historically no implementation, though Java 8+ allows default and static methods.
| Feature | Abstract Class | Interface |
|---|---|---|
| Instantiation | No | No |
| Multiple inheritance | No (single extends) | Yes (multiple implements) |
| Constructors | Yes | No |
| Instance fields | Yes | No (only public static final) |
| Method body | Allowed | Only via default/static (Java 8+) |
| Access modifiers | Any | Methods are public by default |
Use an interface when you want to define what something can do; use an abstract class when you want to provide partial implementation and share state. See Abstract Class vs Interface.
Q14: Can an interface extend another interface?
Yes. An interface can extend one or more other interfaces using extends.
interface Readable { String read(); }
interface Writable { void write(String data); }
interface ReadWrite extends Readable, Writable {} // both!
A class implementing ReadWrite must provide both read() and write().
Common Gotchas
Q15: What is the final keyword in the context of OOP?
The final keyword can be applied to:
- Class — cannot be subclassed (e.g.,
String,Integer) - Method — cannot be overridden by subclasses
- Variable — value cannot be reassigned after initialization
final class ImmutablePoint {
final int x, y;
ImmutablePoint(int x, int y) { this.x = x; this.y = y; }
}
Q16: What is the instanceof operator?
instanceof checks whether an object is an instance of a particular class or interface. It safely returns false for null references.
Animal a = new Dog();
System.out.println(a instanceof Animal); // true
System.out.println(a instanceof Dog); // true
System.out.println(a instanceof Cat); // false
Java 16+ introduced pattern matching for instanceof, letting you combine the check and cast:
if (a instanceof Dog d) {
d.bark(); // d is already cast
}
See Pattern Matching for more.
Q17: What is the difference between aggregation and composition?
Both are HAS-A relationships, but their lifetimes differ:
| Aggregation | Composition | |
|---|---|---|
| Meaning | ”has a” (weak ownership) | “owns a” (strong ownership) |
| Lifetime | Child can exist independently | Child dies when parent dies |
| Example | University has Students | House owns Rooms |
// Aggregation — Student exists independently
class University {
List<Student> students; // just a reference
}
// Composition — Engine cannot exist without Car
class Car {
private final Engine engine = new Engine(); // created inside
}
See Aggregation (HAS-A) for a full walkthrough.
Q18: What is object cloning?
Object cloning creates an identical copy of an object. The Object class provides clone(), but a class must implement the Cloneable marker interface or a CloneNotSupportedException is thrown.
- Shallow copy — copies field values; object references are shared
- Deep copy — recursively copies all referenced objects
class Point implements Cloneable {
int x, y;
Point(int x, int y) { this.x = x; this.y = y; }
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // shallow copy
}
}
Under the Hood
Experienced interviewers often probe the why behind OOP mechanics in the JVM:
- Object layout in heap memory: Every object starts with a header (typically 12–16 bytes) containing a mark word (used by the GC and synchronization) and a class pointer (reference to the class metadata). Instance fields follow.
- vtable resolution: Each class has a virtual method table listing pointers to the actual method implementations. When
a.sound()is called on a parent reference holding aCat, the JVM follows the class pointer toCat’s vtable and callsCat.sound()— this is O(1) dispatch. - Interface dispatch: Interface calls go through an interface method table (itable), which adds a small extra lookup compared to vtable calls — negligible in practice, but visible under extreme microbenchmarks.
- The JIT and inlining: The JIT compiler can observe that
aalways holds aCatat a hot call site and inline the method directly, eliminating the vtable lookup entirely. This is why polymorphism in Java has very low real-world overhead.
Related Topics
- OOP Concepts — the conceptual overview to review before your interview
- Polymorphism — deep dive into compile-time and runtime forms
- Abstract Class vs Interface — the comparison interviewers love to test
- Inheritance — how
extendsworks, with pitfalls - Encapsulation — access control, getters/setters, and design rationale
- Core Java Interview Questions — broader interview prep covering all of Java