Menu
CoddyTech

Four Pillars of OOPs Interview Questions

One question per pillar with runnable code, plus the comparisons that test whether you understand them.

10 questions
  1. What is encapsulation? Explain with an example.

    Encapsulation bundles data with the methods that use it and hides the data behind them, so the object enforces its own rules: private fields, methods that validate every change.

    Java
    public class Main {
        public static void main(String[] args) {
            BankAccount acc = new BankAccount(100);
            acc.withdraw(30);
            System.out.println(acc.getBalance());
            try {
                acc.withdraw(500);
            } catch (IllegalArgumentException e) {
                System.out.println("Refused: " + e.getMessage());
            }
            System.out.println(acc.getBalance());
        }
    }
    
    class BankAccount {
        private int balance;
    
        BankAccount(int opening) { balance = opening; }
    
        int getBalance() { return balance; }
    
        void withdraw(int amount) {
            if (amount <= 0 || amount > balance) {
                throw new IllegalArgumentException("invalid amount " + amount);
            }
            balance -= amount;
        }
    }

    It prints 70, then Refused: invalid amount 500, then 70. A public setBalance() would let callers skip the rule, so getters and setters for everything are not encapsulation.

    Practice it: Min Stack

  2. What is the difference between abstraction and encapsulation?

    Abstraction hides complexity by showing only what an object does; encapsulation hides state by controlling who reads and changes it. Abstraction is the contract (interfaces, abstract classes), encapsulation the implementation (private fields, access modifiers). List lets you add and get without knowing it is an array; ArrayList keeps that array private.

  3. What is inheritance, and what types of inheritance does Java support?

    Inheritance lets a subclass reuse and extend the fields and methods of a superclass, modelling an is-a relation: a Truck is a Vehicle. A Java class extends one class but can implement many interfaces, which since Java 8 can carry default methods. Python and C++ allow several superclasses.

    Java
    public class Main {
        public static void main(String[] args) {
            System.out.println(new Truck("MH12", 8).info());
        }
    }
    
    class Vehicle {
        protected final String plate;
    
        Vehicle(String plate) { this.plate = plate; }
    
        String info() { return "Vehicle " + plate; }
    }
    
    class Truck extends Vehicle {
        private final int tons;
    
        Truck(String plate, int tons) {
            super(plate);
            this.tons = tons;
        }
    
        @Override
        String info() { return super.info() + ", " + tons + " t"; }
    }

    It prints Vehicle MH12, 8 t. More in Java inheritance.

  4. What is polymorphism? What are its types?

    Polymorphism means one interface, many implementations: the same call does different work depending on the object. Compile-time polymorphism is overloading, picked by the compiler from the declared argument types; runtime polymorphism is overriding, picked from the object's actual class.

    Java
    import java.util.List;
    
    public class Main {
        public static void main(String[] args) {
            List<Shape> shapes = List.of(new Circle(1), new Square(2));
            for (Shape s : shapes) {
                System.out.printf("%s %.2f%n", s.getClass().getSimpleName(), s.area());
            }
        }
    }
    
    interface Shape { double area(); }
    
    record Circle(double r) implements Shape {
        public double area() { return Math.PI * r * r; }
    }
    
    record Square(double side) implements Shape {
        public double area() { return side * side; }
    }

    It prints Circle 3.14 and Square 4.00; the loop never checks the type. See Java polymorphism.

  5. What is the difference between static binding and dynamic binding?

    Static (early) binding resolves a call at compile time; dynamic (late) binding resolves it at runtime from the object's actual class. In Java, overloads, static and private methods, constructors and field access are bound statically, so fields are not polymorphic. Overridable instance methods are dynamic: Animal a = new Dog(); a.sound(); runs Dog.sound().

  6. Does private final stop callers from changing a Java list field?

    Java
    import java.util.ArrayList;
    import java.util.List;
    
    public class Main {
        public static void main(String[] args) {
            Team team = new Team();
            team.add("Asha");
            team.getMembers().add("Intruder");
            System.out.println(team.getMembers().size());
        }
    }
    
    class Team {
        private final List<String> members = new ArrayList<>();
    
        void add(String name) { members.add(name); }
    
        List<String> getMembers() { return members; }
    }

    final fixes the reference, not the list. getMembers() hands out the internal list itself, so the caller adds "Intruder" straight into the team and the size is 2, even though the field is private final. Return a copy instead:

    List<String> getMembers() { return List.copyOf(members); }
    

    Now the caller's add throws UnsupportedOperationException.

  7. What is the difference between inheritance and polymorphism?

    Inheritance is about where code comes from: a subclass reuses and extends its parent's fields and methods. Polymorphism is about how a call behaves: one call through a parent type runs the version of whichever object is behind it. Overriding an inherited method is one way to get polymorphism, but interfaces give it without sharing any code, and a class can inherit purely to reuse code without ever being used through its parent type.

  8. Is a Java overload chosen by the argument's runtime type?

    Java
    public class Main {
        static String describe(Object o) { return "Object"; }
    
        static String describe(String s) { return "String"; }
    
        public static void main(String[] args) {
            Object greeting = "hello";
            System.out.println(describe(greeting) + " " + describe("hello"));
        }
    }

    It prints Object String. The compiler picks an overload from the declared type of the argument, and greeting is declared Object even though it holds a String. Only overriding looks at the runtime object. To act on the runtime type, call an overridden method on the object itself, or test it with a pattern such as if (o instanceof String s).

  9. When a parent method calls a method the child overrides, which version runs?

    Java
    public class Main {
        public static void main(String[] args) {
            Report r = new SalesReport();
            System.out.println(r.render());
        }
    }
    
    class Report {
        String render() { return "[" + title() + "]"; }
    
        String title() { return "Report"; }
    }
    
    class SalesReport extends Report {
        @Override
        String title() { return "Sales"; }
    }

    It prints [Sales]. render() is inherited unchanged, but its call to title() means this.title(), and this is a SalesReport, so dynamic dispatch runs the child's version even from parent code. That is the template method pattern: the parent fixes the steps and subclasses fill them in. It is also why calling overridable methods from a parent is risky when the subclass does not expect it.

  10. Can you have polymorphism without inheritance?

    Yes. Inheritance is only one source of it:

    • Interfaces: unrelated classes implement the same contract and share no code.
    • Generics (parametric polymorphism): one List<T> works for any T.
    • Overloading (ad hoc polymorphism): one name, different parameter types.
    • Duck typing in Python: any object with the right method will do.

    What every form needs is a shared contract, not a shared parent class.

Coddy programming languages illustration

Learn to code with Coddy

Get started