Cosmic Module
J
Qubits of DPK
March 14, 2026
Core Java
Layman Explanation
A person can be a son at home, an employee at work, a customer at a shop — same person, different roles/behaviors. In Java, one object can behave differently based on context. That's polymorphism.
What is Polymorphism?
One name, many forms. The ability of an object to take multiple forms.
javascript
QUBITS OF DPK
Dynamic Method Dispatch (Runtime Polymorphism)
When parent reference holds child object — overridden method is called based on ACTUAL object type at runtime.
java
QUBITS OF DPK
JVM decides which method to call at RUNTIME based on actual object type — not the reference type.
Upcasting & Downcasting
Upcasting (automatic)
java
QUBITS OF DPK
Downcasting (manual)
java
QUBITS OF DPK
ClassCastException Trap
java
QUBITS OF DPK
final Keyword
final variable — constant
java
QUBITS OF DPK
final method — cannot override
java
QUBITS OF DPK
final class — cannot extend
java
QUBITS OF DPK
Object Class — Root of All Classes
Every class in Java implicitly extends java.lang.Object.
Key methods from Object class:
java
QUBITS OF DPK
equals() + hashCode() Contract
javascript
QUBITS OF DPK
Wrapper Classes
Each primitive type has a corresponding Wrapper class that wraps it as an Object.
javascript
QUBITS OF DPK
java
QUBITS OF DPK
Why Wrapper Classes?
javascript
QUBITS OF DPK
️ All Traps
java
QUBITS OF DPK
Interview Answer (SDE-2)
"Polymorphism means one interface, multiple implementations. Compile-time polymorphism via method overloading, runtime polymorphism via method overriding with dynamic method dispatch — JVM decides which overridden method to call based on actual object type. Upcasting is automatic (child to parent reference), downcasting is manual and can throw ClassCastException if actual type doesn't match. Final prevents variable reassignment, method overriding, and class extension — String is final. Every class extends Object implicitly, providing equals, hashCode, and toString — always override equals and hashCode together. Wrapper classes box primitives as objects for use in collections and generics."
Interview Questions & MAANG-Level Answers
Q1. What is polymorphism? What are its types?
Polymorphism means one interface, many implementations. Two types: (1) Compile-time (static) via method overloading — same method name, different parameters, resolved at compile time. (2) Runtime (dynamic) via method overriding — parent reference holds child object, JVM decides at runtime which override to call based on actual object type, not reference type. Runtime polymorphism enables writing generic code that works for future subtypes not yet created.
Q2. What is dynamic method dispatch?
When an overridden method is called on a parent reference, JVM determines which implementation to execute based on the ACTUAL object type at runtime:
java
QUBITS OF DPK
This is resolved at runtime, not compile time. It's the foundation of the Open/Closed principle — code open for extension (new subtypes), closed for modification (existing code doesn't change). Static methods are NOT dispatched dynamically — they're resolved by reference type.
Q3. What is the difference between upcasting and downcasting?
Upcasting: child object assigned to parent reference — automatic, safe, no cast needed. Restricts access to parent's methods only. Animal a = new Dog() — a can only call Animal methods. Downcasting: parent reference cast back to child type — manual, risky. Dog d = (Dog) a — works only if a actually holds a Dog at runtime, else ClassCastException. Always use instanceof check before downcasting.
Q4. What is ClassCastException and how to prevent it?
Thrown when you try to cast an object to a type it doesn't actually belong to: Animal a = new Cat(); Dog d = (Dog) a — runtime crash. Prevention: use instanceof check first:
java
QUBITS OF DPK
Java 16+ pattern matching makes this cleaner: if (a instanceof Dog d) { d.bark(); } — combines check and cast. In well-designed OOP, excessive downcasting suggests a design smell — prefer polymorphism instead.
Q5. What are the uses of the final keyword?
Three uses: (1) final variable — constant, cannot be reassigned after initialization. final double PI = 3.14. (2) final method — cannot be overridden in subclasses. Prevents unintended behavior changes. (3) final class — cannot be extended. String, Integer, Math are all final. Used for security (prevent subclass attacks), immutability, and optimization (JVM can inline final methods).
Q6. What is the contract between equals() and hashCode()?
The contract: if a.equals(b) is true, then a.hashCode() == b.hashCode() MUST be true. The reverse is not required (same hash doesn't mean equal). If you break this contract, HashMap and HashSet break — objects that are "equal" end up in different buckets and can't be found. ALWAYS override both together. Use Objects.hash(field1, field2) for hashCode. IDEs and Lombok can auto-generate correct implementations.
Q7. What is autoboxing and unboxing?
Autoboxing: automatic conversion from primitive to wrapper object: Integer i = 5 (int → Integer). Unboxing: automatic conversion from wrapper to primitive: int x = i (Integer → int). These happen implicitly in assignments, method calls, and arithmetic. Performance note: heavy autoboxing in loops creates many short-lived objects — prefer primitives in performance-critical code. NPE risk: unboxing null wrapper throws NullPointerException.
Q8. Why is Integer 127 == 127 true but Integer 128 == 128 false?
Java caches Integer objects from -128 to 127 in the Integer Cache (IntegerCache class). Values in this range always return the same cached object, so == (reference comparison) returns true. Values outside this range create new heap objects each time, so == returns false even with same value. Always use .equals() for Integer comparison — it works for ALL values regardless of cache range. This behavior is in the Java spec and is intentional for performance.