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.
Javapublic 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 7andSTRING HI. See method overloading.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 asBigDecimal.add.Pythonclass 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.Do fields get overridden like methods in Java?
Javapublic 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.nameis resolved at compile time from the reference typeAnimal, whilea.getName()is overridden and dispatched at runtime toDog. 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.What happens when a Java subclass redeclares a parent's static method?
Javapublic 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()callsParent.who(), while the instance methodme()is dispatched at runtime toChild.@Overrideon a static method is a compile error.Which overload does Java pick for
show(null)?Javapublic 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); } }nullmatches both overloads, and Java picks the most specific:Stringis a subtype ofObject, soshow(String)wins.Follow-up: what if you add
show(Integer i)? The call stops compiling as ambiguous, because neitherStringnorIntegeris more specific; choose withshow((Integer) null).Why does Java not support multiple inheritance of classes? What is the diamond problem?
If
Dinherits fromBandC, and both override a method ofA, which version doesDget? Java avoids this for classes by allowing one superclass. Interfacedefaultmethods can still clash, and then the class must override and choose:Javapublic 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.What happens when a Java constructor calls an overridable method?
Javapublic 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 beforeDerived's field initializers, but the object is already aDerived, sodescribe()dispatches to the override and readsnamewhile it is stillnull. C++ differs: duringBase's constructor a virtual call runsBase::describe(). The rule from Effective Java: constructors must not call overridable methods.What is upcasting and downcasting? What does
instanceofdo?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 throwsClassCastExceptionif the object is not that type.instanceofchecks first, and since Java 16 binds a variable:Javapublic 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.What does
finalmean on a variable, a method and a class?finalmeans it cannot change further. Afinalvariable is assigned once, afinalmethod cannot be overridden, and afinalclass cannot be extended (String,Integer). The trap: afinalreference is not an immutable object.final List<String> listcannot point to another list, butlist.add("x")still works.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
Dogget aDogback without a cast. Parameters have no such freedom: changing a parameter type creates an overload, not an override.
Inheritance and Polymorphism Interview Questions
Overloading versus overriding, what is polymorphic in Java, the diamond problem, and the output questions most candidates miss.