Polymorphism isn't magic. It's a Lookup Table. I wrote Java for 3 years before I actually understood how the JVM handles Overriding. I relied on the standard university rule: "Method calls are determined by the actual Object type, not the Reference type." While this explains what happens, it doesn't explain how. I imagined the JVM frantically "searching" up the inheritance tree at runtime—scanning the Child class, then the Parent—until it found the method. Architecturally, that would be a disaster. If the JVM had to search the hierarchy (O(N)) for every method call, Java would be too slow for high-performance systems. The JVM avoids this search entirely using vTables (Virtual Method Tables). The Scenario: Imagine we have class B extends A. A has a method print() B overrides show() but inherits print() The Mechanics (Visualized below): Load Time: When Class B is loaded, the JVM builds a hidden array of function pointers. The "Cheat": Since B inherits print(), the JVM simply copies the memory address from A's table into B's table. Runtime: When you run A obj = new B() and call obj.show(), the JVM follows the object in Heap, jumps to the fixed index in the vTable, and runs the code. As the diagram shows: Solid Arrow: The overridden method points to the new B.show() code. Dashed Arrow: The inherited method points back to the existing A.print() code. The Lesson: Efficient systems rarely rely on runtime decisions if they can pre-calculate the answer at load time. (PS: I share more System Design deep dives like this on X. Link in comments 👇) #Java #JVM #SystemDesign #SoftwareArchitecture
Yajat Dhand’s Post
More Relevant Posts
-
Today I solved LeetCode 77 – Combinations using a backtracking approach. The problem asks us to generate all possible combinations of k numbers chosen from 1 to n. Instead of brute force, I used recursion with pruning to reduce unnecessary calls and improve efficiency. Key idea: Build combinations step by step Backtrack when the size reaches k Prune branches where remaining elements are insufficient Here is my Java solution: class Solution { List<List<Integer>> sol = new ArrayList<>(); public List<List<Integer>> combine(int n, int k) { generate(1, n, k, new ArrayList<>()); return sol; } public void generate(int i, int n, int k, List<Integer> sub) { if (k == 0) { sol.add(new ArrayList<>(sub)); return; } for (int j = i; j <= n - k + 1; j++) { sub.add(j); generate(j + 1, n, k - 1, sub); sub.remove(sub.size() - 1); } } } Time Complexity: O(C(n, k)) Space Complexity: O(k) This problem strengthened my understanding of recursion, pruning, and combinatorial generation. Always open to feedback and discussions. #LeetCode #Java #Backtracking #ProblemSolving #CodingJourney
To view or add a comment, sign in
-
🚫 Can we override a static method in an interface? No. And here’s the real reason why 👇 In Java, static methods belong to the type (class/interface), not to objects. That single rule explains everything. ❌ Static methods in interfaces cannot be overridden Why? Overriding depends on runtime polymorphism Static methods are resolved at compile time So JVM never does dynamic dispatch for static methods ➡️ No runtime decision = no overriding ✅ What happens instead? Method Hiding If an implementing class defines a static method with the same signature: interface Payment { static void pay() { System.out.println("Interface payment"); } } class CardPayment implements Payment { static void pay() { System.out.println("Class payment"); } } Calls behave like this: Payment.pay(); // Interface payment CardPayment.pay(); // Class payment This is method hiding, not overriding. 🧠 Key rule most devs miss Static methods in interfaces are NOT inherited by implementing classes. That’s why: @Override ❌ is not allowed Calls depend on reference/type, not object 🔍 Overriding vs Method Hiding Concept Overriding Method Hiding Method type Instance Static Binding Runtime Compile-time Polymorphism ✅ Yes ❌ No @Override Allowed ❌ Error Based on Object Reference 🏗️ Architect’s takeaway If behavior must change at runtime, don’t use static methods. Use instance methods or default methods in interfaces. Static methods are great for utilities, not behavior. 💬 Interview tip: If someone says “static methods can be overridden” — that’s a red flag. Agree? Disagree? Drop your thoughts 👇 #Java #SpringBoot #BackendDevelopment #CleanCode #SystemDesign #JavaInterview #SoftwareArchitecture
To view or add a comment, sign in
-
𝐓𝐡𝐢𝐬 𝐜𝐨𝐝𝐞 𝐬𝐧𝐢𝐩𝐩𝐞𝐭 𝐢𝐬 𝐞𝐧𝐨𝐮𝐠𝐡 𝐭𝐨 𝐜𝐨𝐧𝐟𝐮𝐬𝐞 𝐬𝐨𝐦𝐞𝐨𝐧𝐞 𝐰𝐢𝐭𝐡 𝐉𝐚𝐯𝐚. 😁 Let me introduce you to the concept of wrapper classes and autoboxing first. 𝐖𝐑𝐀𝐏𝐏𝐄𝐑 𝐂𝐋𝐀𝐒𝐒𝐄𝐒: These are classes used to wrap primitive values so we can treat them like objects. This is essential for the Collection framework (like ArrayList), which only works with objects. 𝐀𝐔𝐓𝐎𝐁𝐎𝐗𝐈𝐍𝐆: The process of converting primitive values to wrapper objects is implicit. We don't need the new keyword. Now let's discuss the code: 𝐂𝐎𝐃𝐄 1: 𝘪𝘯𝘵 𝘢 = 100; 𝘪𝘯𝘵 𝘣 = 100; These are primitive values. For primitives, the == operator compares the actual values. Since both are 100, the output is 𝐭𝐫𝐮𝐞. 𝐂𝐎𝐃𝐄 2: Integer wrapper classes have an Integer Cache. By default, Java caches all Integer objects in the range of -128 to 127. 𝘐𝘯𝘵𝘦𝘨𝘦𝘳 𝘱 = 100; 𝘐𝘯𝘵𝘦𝘨𝘦𝘳 𝘲 = 100; Since 100 is in the cache, Java points both variables to the same object memory location. The output is 𝐭𝐫𝐮𝐞. 𝐂𝐎𝐃𝐄 3: 𝘐𝘯𝘵𝘦𝘨𝘦𝘳 𝘺 = 128; 𝘐𝘯𝘵𝘦𝘨𝘦𝘳 𝘻 = 128; Because 128 is outside the cache range, Java creates two distinct objects in memory. Since == compares memory references for objects, the output is 𝐟𝐚𝐥𝐬𝐞. ~Anuprash Gautam 🍵 𝘒𝘦𝘦𝘱 𝘭𝘦𝘢𝘳𝘯𝘪𝘯𝘨 𝘢𝘯𝘥 𝘣𝘳𝘦𝘸𝘪𝘯𝘨 𝘤𝘰𝘧𝘧𝘦𝘦.😊 #Java #programming #autoboxing #oops
To view or add a comment, sign in
-
-
For a long time, Java polymorphism was something I knew how to implement but didn’t truly used it to real analogy. Today, it finally clicked. All the scattered pieces I had learned earlier — references, inheritance, overloading, overriding — connected into one clear mental model. The breakthrough was realizing that Java makes two different decisions at two different times: At compile time The compiler looks only at the reference type It decides which method signatures are allowed Overloading is resolved here, not at runtime At runtime The JVM looks at the actual object in heap memory If a method is overridden, dynamic dispatch decides which implementation runs This is where true runtime polymorphism happens So in code like: Animal a = new Dog(); The reference (Animal) controls what can be called The object (Dog) controls what actually executes Method selection and method execution are two separate steps This also clarified a big misconception: Same method name does not mean polymorphism Runtime polymorphism requires overriding with the same signature Overloading is a compile-time feature, not dynamic behavior What changed for me today wasn’t new syntax — it was understanding how the compiler, JVM, and memory model cooperate behind the scenes. That shift from memorizing rules to building a mental model makes all the difference. #Java #OOP #Polymorphism #LearningInPublic #AutomationTesting
To view or add a comment, sign in
-
Today I learned an important OOPs concept – Abstraction 🧠🪁 👉 Abstraction means showing only the essential features and hiding the internal implementation. Real-time example: When we fly a kite, we know how to fly it using the thread, but we don’t know how the kite stays in the air. The internal working is hidden — this is abstraction. In Java: Abstraction shows the method signature and hides the method logic from the user. Learning step by step and enjoying the process 💻✨ // Abstract class abstract class Kite { abstract void fly(); // method signature } // Child class class PaperKite extends Kite { void fly() { System.out.println("Kite flies using wind"); } } // Main class public class Test { public static void main(String[] args) { Kite k = new PaperKite(); k.fly(); } }
To view or add a comment, sign in
-
Why does Go have no NullPointerException? Because Go doesn't treat "not initialized" as a normal state. In Java, a null reference is a landmine. In Go, declaration creates a real value immediately and many "empty" states still behave safely. 🗂️ In this new article, I walk through: 🔹 Declaration == initialization var x int is already a valid value: 0. 🔹 Zero values are design tools They let you build APIs where the default state is usable: empty string, zero counters, ready-to-use mutexes. 🔹 nil that behaves (within boundaries) Nil slices: len, range, append work. Nil maps: reads work; writes require make. So "check for nil everywhere" stops being the default programming posture. 🔹 The typed-nil interface trap A nil pointer inside an interface can still produce a non-nil interface value. If you've ever returned error and got surprised: this is why. 📚 Read Part 3 for more (Go Value Philosophy): https://lnkd.in/gPRsJjYF #golang #go #backend #systems #java #python
To view or add a comment, sign in
-
Merge Sort in Java may look complex, but most mistakes happen because: • we don’t clearly understand how the array is divided • we mix up the merge logic • we forget that sorting actually happens during the merge step The core idea is straightforward: divide the array into smaller parts, sort them recursively, and then merge them back in sorted order. What really happens: – The array is repeatedly divided until each part has one element – A single element is already sorted by definition – Then, pairs of sorted subarrays are merged to form bigger sorted arrays So: – First, size-1 arrays are merged into size-2 sorted arrays – Then size-2 into size-4 – Then size-4 into size-8 – And so on, until the whole array is sorted The key insight: 👉 All the real sorting happens during merging, not during splitting. Once you understand that: • recursion just breaks the problem into smaller pieces • merge logic ensures order • time complexity stays O(n log n) in all cases Merge Sort isn’t about simplicity — it’s about guaranteed performance and clean divide-and-conquer thinking. That’s what makes it a foundation algorithm for: ✔ large datasets ✔ external sorting ✔ stable sorting requirements #Java #MergeSort #DSA #Algorithms #DivideAndConquer #ProblemSolving #BackendEngineering
To view or add a comment, sign in
-
📌 DSA Problem Series – Day 15 | Problem 2 | Array 🔹 Problem: Missing and Repeating Number 🧠 Problem Statement: You are given an array of size N containing numbers from 1 to N. One number is missing One number is repeating Your task is to find both numbers. ✅ Approach Used Use a HashMap to track frequency of elements Identify the repeating number when frequency > 1 Use mathematical sum formula to compute the missing number 💻 Java Solution class Solution { ArrayList<Integer> findTwoElement(int arr[]) { Map<Integer, Integer> map = new HashMap<>(); int n = arr.length; int expectedSum = n * (n + 1) / 2; int repeatingNumber = -1; int actualSum = 0; for (int item : arr) { if (map.containsKey(item)) { repeatingNumber = item; } map.put(item, map.getOrDefault(item, 0) + 1); actualSum += item; } int missingNumber = expectedSum - (actualSum - repeatingNumber); return new ArrayList<>(Arrays.asList(repeatingNumber, missingNumber)); } } ⏱️ Complexity Time Complexity: O(N) Space Complexity: O(N) 🎯 Key Takeaway Combining hashing with basic mathematics makes this problem simple and efficient. This pattern appears frequently in interviews and competitive programming. #DSA #Java #ProblemSolving #Arrays #CodingInterview #LeetCode #HashMap #Backend
To view or add a comment, sign in
-
-
🛑 The "Silent" Methods of the Object Class: wait, notify, and notifyAll ➡️ We often talk about toString(), equals(), and hashCode(), but the Object class holds three powerful methods that manage how processes synchronize around an instance. These aren't just utility methods; they are the foundation of coordination in Java. 🔍 Why are they in the Object class? ➡️ In Java, every object has an intrinsic lock (or monitor). By placing these methods in the Object class, Java allows any instance to act as a synchronization point. 🛠 The Mechanics 🔹 wait(): Forces the current execution to pause and release the lock on the object. It essentially puts the process in a "waiting room" until another entity signals it to move. 🔹 notify(): Picks a single waiting process and moves it back to the "runnable" state. It’s a tap on the shoulder for one participant. 🔹 notifyAll(): Sends a signal to every participant waiting on that specific object’s lock. 💡 Implementation Essentials ✔️ To use these, you must abide by two strict rules: 🔹Ownership: You must own the object's monitor (be inside a synchronized block). 🔹 The Loop Check: Always call wait() inside a loop. This protects your logic against "spurious wakeups"—when a process wakes up without a signal. // Standard pattern for object coordination synchronized(sharedObject) { while(conditionNotMet) { sharedObject.wait(); } // Execute logic once condition is true } #Java #ProgrammingTips #SoftwareArchitecture #ObjectOriented #Coding
To view or add a comment, sign in
-
Day 42 - LeetCode Journey 🚀 Solved LeetCode 944: Delete Columns to Make Sorted in Java ✅ Today’s challenge was all about looking at data from a different perspective—literally! Instead of the usual row-by-row string processing, I had to shift my focus to vertical column-wise traversal. The Problem: Given an array of strings, imagine them stacked to form a grid. The goal is to identify and "delete" any columns that are not sorted lexicographically. The Approach: Grid Traversal: Used nested loops where the outer loop iterates through columns and the inner loop iterates through rows. Lexicographical Check: For each column, I compared characters at index row and row + 1. Optimization: As soon as a single out-of-order pair is found in a column, the break keyword ensures we stop checking that column and move to the next, keeping the solution efficient. Key Takeaways: Column-Major Order: Reinforced how to swap the standard matrix[i][j] traversal to focus on vertical data. String Manipulation: Continued practicing charAt() for precise character comparisons within a string array. Problem Decomposition: Breaking down a visual grid into simple loop logic is a crucial skill for more complex matrix problems. Whether it's pattern matching or grid manipulation, every problem is a new tool in the kit. Consistency is doing its work! 💪 #LeetCode #DSA #Java #Strings #Algorithms #ProblemSolving #CodingPractice #InterviewPreparation #Consistency #DailyCoding
To view or add a comment, sign in
-
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development
The fetch/decode/execute cycle is a lookup table; all else follows.