Menu
CoddyTech

Inheritance and Polymorphism Interview Questions

Overloading versus overriding, what is polymorphic in Java, the diamond problem, and the output questions most candidates miss.

10 questions
  1. What is the difference between method overloading and method overriding?

    Overloading is several methods with the same name and different parameter lists, chosen at compile time from the argument types. Overriding is a subclass replacing an inherited method with the same signature, chosen at runtime from the object.

    Java
    public class Main {
        public static void main(String[] args) {
            Printer p = new LoudPrinter();
            p.print(7);
            p.print("hi");
        }
    }
    
    class Printer {
        void print(int x) { System.out.println("int " + x); }
    
        void print(String s) { System.out.println("String " + s); }
    }
    
    class LoudPrinter extends Printer {
        @Override
        void print(String s) { System.out.println("STRING " + s.toUpperCase()); }
    }

    It prints int 7 and STRING HI. See method overloading.

  2. What is operator overloading? Does Java support it?

    Operator overloading lets a class define what an operator such as + or == does for its objects. C++ (operator+) and Python (__add__, __eq__) support it. Java does not, apart from the built-in + on strings, so you call methods such as BigDecimal.add.

    Python
    class Vector:
        def __init__(self, x, y):
            self.x, self.y = x, y
    
        def __add__(self, other):
            return Vector(self.x + other.x, self.y + other.y)
    
        def __eq__(self, other):
            return isinstance(other, Vector) and (self.x, self.y) == (other.x, other.y)
    
        def __repr__(self):
            return f"Vector({self.x}, {self.y})"
    
    print(Vector(1, 2) + Vector(3, 4), Vector(1, 2) == Vector(1, 2))

    It prints Vector(4, 6) True. See C++ operator overloading.

  3. Do fields get overridden like methods in Java?

    Java
    public class Main {
        public static void main(String[] args) {
            Animal a = new Dog();
            System.out.println(a.name + " " + a.getName());
        }
    }
    
    class Animal {
        String name = "Animal";
    
        String getName() { return name; }
    }
    
    class Dog extends Animal {
        String name = "Dog";
    
        @Override
        String getName() { return name; }
    }

    Methods are polymorphic, fields are not. a.name is resolved at compile time from the reference type Animal, while a.getName() is overridden and dispatched at runtime to Dog. A subclass field with the same name hides the parent's, and both exist in the object. It compiles, and it is almost always a bug.

  4. What happens when a Java subclass redeclares a parent's static method?

    Java
    public class Main {
        public static void main(String[] args) {
            Parent p = new Child();
            System.out.println(p.who() + " " + p.me());
        }
    }
    
    class Parent {
        static String who() { return "Parent"; }
    
        String me() { return "Parent"; }
    }
    
    class Child extends Parent {
        static String who() { return "Child"; }
    
        @Override
        String me() { return "Child"; }
    }

    Static methods are hidden, not overridden. A static call binds at compile time to the reference type, so p.who() calls Parent.who(), while the instance method me() is dispatched at runtime to Child. @Override on a static method is a compile error.

  5. Which overload does Java pick for show(null)?

    Java
    public class Main {
        static void show(Object o) { System.out.println("Object"); }
    
        static void show(String s) { System.out.println("String"); }
    
        public static void main(String[] args) {
            show(null);
        }
    }

    null matches both overloads, and Java picks the most specific: String is a subtype of Object, so show(String) wins.

    Follow-up: what if you add show(Integer i)? The call stops compiling as ambiguous, because neither String nor Integer is more specific; choose with show((Integer) null).

  6. Why does Java not support multiple inheritance of classes? What is the diamond problem?

    If D inherits from B and C, and both override a method of A, which version does D get? Java avoids this for classes by allowing one superclass. Interface default methods can still clash, and then the class must override and choose:

    Java
    public class Main {
        public static void main(String[] args) {
            System.out.println(new SmartPhone().click());
        }
    }
    
    interface Camera {
        default String click() { return "photo"; }
    }
    
    interface Phone {
        default String click() { return "call"; }
    }
    
    class SmartPhone implements Camera, Phone {
        @Override
        public String click() { return Camera.super.click() + " + " + Phone.super.click(); }
    }

    It prints photo + call; without the override it does not compile. Python resolves the diamond with the MRO.

  7. What happens when a Java constructor calls an overridable method?

    Java
    public class Main {
        public static void main(String[] args) {
            new Derived();
        }
    }
    
    class Base {
        Base() { describe(); }
    
        void describe() { System.out.println("base"); }
    }
    
    class Derived extends Base {
        String name = "derived";
    
        @Override
        void describe() { System.out.println("name=" + name); }
    }

    Base's constructor runs before Derived's field initializers, but the object is already a Derived, so describe() dispatches to the override and reads name while it is still null. C++ differs: during Base's constructor a virtual call runs Base::describe(). The rule from Effective Java: constructors must not call overridable methods.

  8. What is upcasting and downcasting? What does instanceof do?

    Upcasting treats a subclass object as its parent type (Animal a = new Dog();) and is always safe. Downcasting goes back (Dog d = (Dog) a;) and throws ClassCastException if the object is not that type. instanceof checks first, and since Java 16 binds a variable:

    Java
    public class Main {
        public static void main(String[] args) {
            Object[] things = { "hello", 42, 3.5 };
            for (Object o : things) {
                if (o instanceof String s) {
                    System.out.println("String of length " + s.length());
                } else if (o instanceof Integer i) {
                    System.out.println("Integer doubled " + (i * 2));
                } else {
                    System.out.println("Other: " + o.getClass().getSimpleName());
                }
            }
        }
    }

    It prints String of length 5, Integer doubled 84, Other: Double.

  9. What does final mean on a variable, a method and a class?

    final means it cannot change further. A final variable is assigned once, a final method cannot be overridden, and a final class cannot be extended (String, Integer). The trap: a final reference is not an immutable object. final List<String> list cannot point to another list, but list.add("x") still works.

  10. What is a covariant return type?

    A covariant return type lets an overriding method return a subtype of the parent method's return type (Java 5 and later).

    class Animal {
        Animal reproduce() { return new Animal(); }
    }
    
    class Dog extends Animal {
        @Override
        Dog reproduce() { return new Dog(); }   // Dog is a subtype of Animal
    }
    

    Callers holding a Dog get a Dog back without a cast. Parameters have no such freedom: changing a parameter type creates an overload, not an override.

Coddy programming languages illustration

Learn to code with Coddy

Get started