Skills & Technologies

Java Interview Questions & Answers: OOP to JVM Internals

19 min readUpdated March 16, 2025
JavaOOPJVM
Java remains one of the most in-demand programming languages for enterprise software, backend services, Android development, and large-scale distributed systems. Java interviews are thorough — they test not only your ability to write correct code but also your understanding of the JVM, memory model, concurrency primitives, and enterprise frameworks. This guide covers the Java interview questions you are most likely to encounter, from core object-oriented principles and the collections framework to advanced topics like multithreading, JVM garbage collection, and Spring Boot. Each answer provides the depth and structure needed to demonstrate senior-level expertise.

OOP Principles & Core Java

Java interviews always start with object-oriented fundamentals. Interviewers assess your understanding of: • Four pillars of OOP — encapsulation, inheritance, polymorphism, abstraction • Design principles — SOLID principles, composition vs inheritance • Java-specific features — interfaces vs abstract classes, generics, enums, records • Modern Java — sealed classes, pattern matching, virtual threads (Java 21+)

Q1.Explain the SOLID principles with Java examples. Why do they matter?

intermediate
SOLID is a set of five design principles that help you write maintainable, extensible object-oriented code. S — Single Responsibility Principle: • A class should have only one reason to change • Example: separate UserValidator, UserRepository, and UserNotifier instead of putting all logic in a UserService god class O — Open/Closed Principle: • Classes should be open for extension but closed for modification • Example: use a PaymentStrategy interface with CreditCardPayment, PayPalPayment implementations instead of if-else chains in the payment method L — Liskov Substitution Principle: • Subtypes must be substitutable for their base types without breaking the program • Example: if Square extends Rectangle, setting width should not unexpectedly change height — if it does, the hierarchy is wrong I — Interface Segregation Principle: • Clients should not be forced to depend on interfaces they don't use • Example: split a large Worker interface into Workable, Feedable, Sleepable — a robot implements Workable but not Feedable D — Dependency Inversion Principle: • High-level modules should depend on abstractions, not concrete implementations • Example: OrderService depends on NotificationSender interface, not directly on EmailSender — allows swapping to SMS or push notifications Why they matter: SOLID principles reduce coupling, improve testability, and make code easier to extend. In Spring Boot applications, dependency injection naturally supports DIP, and interface-based design supports OCP and ISP.

Q2.What is the difference between an interface and an abstract class in Java? When should you use each?

beginner
Since Java 8+, the line between interfaces and abstract classes has blurred, but important differences remain. Interfaces: • Define a contract — what a class can do • Support multiple inheritance (a class can implement many interfaces) • Can contain: abstract methods, default methods (Java 8+), static methods, constants • Cannot contain: instance fields, constructors, or mutable state • Use when: defining a capability or role that multiple unrelated classes share (e.g., Comparable, Serializable, Iterable) Abstract classes: • Define a partial implementation — a template that subclasses complete • Single inheritance only (a class can extend only one abstract class) • Can contain: everything interfaces can, plus instance fields, constructors, and mutable state • Use when: classes share common state and behavior, and you want to provide a reusable base implementation (e.g., AbstractList, AbstractMap) Decision guide: • Need multiple inheritance? → Interface • Need shared mutable state or constructor logic? → Abstract class • Defining a capability ("can do")? → Interface • Defining an identity ("is a")? → Abstract class • Not sure? → Default to interface — it's more flexible Modern Java additions: • Sealed classes (Java 17) — restrict which classes can extend/implement a type, enabling exhaustive pattern matching • Records (Java 16) — immutable data carriers that auto-generate equals, hashCode, toString

Collections Framework & Multithreading

The Java Collections Framework and concurrency are heavily tested in senior interviews: • Collections — List, Set, Map, Queue interfaces and their key implementations • Internals — HashMap internals (buckets, load factor, tree-ification), ConcurrentHashMap segments • Concurrency primitives — synchronized, volatile, ReentrantLock, Atomic classes • Thread pools — ExecutorService, ForkJoinPool, CompletableFuture, virtual threads

Q3.How does HashMap work internally in Java? What happens during collisions?

intermediate
Internal structure: A HashMap uses an array of buckets (default size 16). Each bucket stores a linked list (or a balanced tree for large buckets) of key-value pairs. Put operation: 1. Compute the key's hashCode() 2. Apply a secondary hash function to reduce collisions: hash = hashCode ^ (hashCode >>> 16) 3. Calculate the bucket index: index = hash & (capacity - 1) 4. If the bucket is empty, store the entry 5. If the bucket has entries (collision), walk the linked list and check equals() for each key 6. If a matching key is found, replace the value; otherwise, append to the list Collision handling (Java 8+ optimization): • When a bucket's linked list exceeds 8 entries (TREEIFY_THRESHOLD), it converts to a balanced red-black tree • This improves worst-case lookup from O(n) to O(log n) • When the tree shrinks below 6 entries (UNTREEIFY_THRESHOLD), it converts back to a linked list Resizing: • Load factor default is 0.75 — when 75% of buckets are filled, the array doubles in size • All entries are rehashed and redistributed (expensive operation) • Capacity is always a power of 2 (enables the bitwise index calculation) Key contract: • Objects used as keys MUST correctly implement both hashCode() and equals() • If two objects are equal (equals() returns true), they must have the same hashCode() • Violating this contract causes silent data loss in the map

Q4.Explain the Java memory model. What is the difference between volatile and synchronized?

advanced
The Java Memory Model (JMM) defines how threads interact through memory and what behaviors are guaranteed in concurrent programs. The problem JMM solves: • Each thread may cache variables locally (CPU registers, L1/L2 cache) • Without synchronization, one thread's writes may not be visible to another thread • The compiler and CPU may reorder instructions for performance volatile keyword: • Guarantees visibility — a write to a volatile variable is immediately visible to all threads • Prevents reordering — instructions before a volatile write cannot be moved after it (and vice versa for reads) • Does NOT guarantee atomicity — count++ on a volatile variable is still a race condition (read-modify-write) • Use when: a single variable is written by one thread and read by others (e.g., a shutdown flag) synchronized keyword: • Guarantees visibility (like volatile) + atomicity + mutual exclusion • Only one thread can hold the monitor (lock) at a time • Ensures a happens-before relationship — all actions before the unlock are visible to any thread that subsequently acquires the same lock • Use when: you need to protect a critical section of code that involves multiple operations Comparison: • volatile — lightweight, no locking, for single variable visibility • synchronized — heavier, acquires a lock, for compound actions (check-then-act, read-modify-write) • ReentrantLock — more flexible than synchronized (try-lock, timed lock, fair locking) • AtomicInteger/AtomicReference — lock-free atomic operations using CAS (compare-and-swap) Virtual threads (Java 21+): • Lightweight threads managed by the JVM, not the OS • Enable millions of concurrent tasks without thread pool sizing headaches • Use synchronized carefully with virtual threads — prefer ReentrantLock to avoid pinning the carrier thread

JVM Internals & Spring Boot

Senior Java roles require understanding of JVM internals and the Spring ecosystem: • JVM architecture — class loading, JIT compilation, memory areas (heap, stack, metaspace) • Garbage collection — GC algorithms (G1, ZGC, Shenandoah), tuning GC pauses, memory leak diagnosis • Spring Boot — dependency injection, auto-configuration, Spring Data, Spring Security • Production readiness — profiling, monitoring, performance tuning

Q5.How does garbage collection work in Java? Compare G1, ZGC, and Shenandoah collectors.

advanced
Java's garbage collector automatically reclaims memory from objects that are no longer reachable. Understanding GC is critical for performance-sensitive applications. Core concepts: • Generational hypothesis — most objects die young, so the heap is divided into Young Generation (Eden + Survivor spaces) and Old Generation • Minor GC — collects the young generation (fast, frequent) • Major/Full GC — collects the entire heap (slow, infrequent, causes pauses) G1 Garbage Collector (default since Java 9): • Divides the heap into equal-sized regions rather than fixed generations • Prioritizes collecting regions with the most garbage first ("Garbage-First") • Target pause times configurable: -XX:MaxGCPauseMillis=200 • Good for: general-purpose applications with heap sizes from 4GB to 64GB ZGC (production-ready since Java 15): • Ultra-low-latency collector — sub-millisecond pause times regardless of heap size • Uses colored pointers and load barriers for concurrent relocation • Handles heaps up to 16TB • Good for: latency-sensitive applications (trading systems, real-time services) Shenandoah: • Similar low-pause goals as ZGC but uses a different approach (Brooks forwarding pointers) • Concurrent compaction without stopping application threads • Good for: applications requiring low latency with OpenJDK distributions Tuning tips: • Start with G1 defaults — only tune if you observe GC-related performance issues • Monitor with: -Xlog:gc*, GC log analysis tools (GCViewer, GCEasy) • Common issues: frequent Full GCs (heap too small), long GC pauses (consider ZGC), memory leaks (use heap dumps + MAT)

Q6.How does Spring Boot's dependency injection work? What is the difference between @Component, @Service, @Repository, and @Controller?

intermediate
Dependency Injection (DI) in Spring: DI is the mechanism by which Spring creates objects (beans) and wires their dependencies automatically, following the Dependency Inversion Principle. How it works: 1. Component scanning — Spring scans the classpath for classes annotated with stereotype annotations 2. Bean creation — Spring creates singleton instances (by default) of discovered classes 3. Dependency resolution — Spring injects required dependencies via constructor, setter, or field injection 4. Lifecycle management — Spring manages the entire lifecycle (creation, initialization, destruction) Injection types (preference order): • Constructor injection (recommended) — dependencies declared in constructor, supports immutability and easy testing • Setter injection — for optional dependencies • Field injection (@Autowired on fields) — discouraged, hides dependencies, harder to test Stereotype annotations: • @Component — generic Spring-managed bean (the base annotation) • @Service — semantically marks business logic layer (functionally identical to @Component) • @Repository — data access layer; adds automatic exception translation (wraps JDBC exceptions into Spring's DataAccessException) • @Controller / @RestController — web layer; enables request mapping and response handling Why the distinction matters: • Semantic clarity — developers instantly understand a class's role • AOP targeting — you can apply aspects (logging, transactions) to specific stereotypes • @Repository has real technical behavior (exception translation) • @Controller enables Spring MVC request handling Best practice: Use constructor injection exclusively. It makes dependencies explicit, supports immutability (final fields), and makes unit testing straightforward (just pass mocks to the constructor).

Frequently Asked Questions

Which Java version should I prepare for in interviews?+

Target Java 17 (LTS) as your baseline — it includes records, sealed classes, pattern matching for instanceof, text blocks, and switch expressions. Be aware of Java 21 features (virtual threads, sequenced collections, pattern matching for switch) as bonus knowledge. Most enterprise applications run Java 11 or 17, so avoid relying on features newer than 17 unless the job specifically uses them.

How important is Spring Boot knowledge for Java interviews?+

For backend/enterprise Java roles, Spring Boot knowledge is typically expected. Understand dependency injection, auto-configuration, REST API development with Spring Web, data access with Spring Data JPA, and security basics with Spring Security. For roles at companies using different frameworks (Quarkus, Micronaut), focus on core Java and general framework concepts — the principles transfer.

Should I also learn Kotlin for Java interviews?+

Not unless the role specifically requires it. For Android development roles, Kotlin is now the primary language. For backend roles, Java is still dominant, but Kotlin interoperability knowledge is a plus at companies using both. Focus on deep Java mastery first — Kotlin is easy to pick up once you know Java well.

Ready to land your dream job?

CareerUplift gives you AI-powered mock interviews, an ATS-optimized resume builder, and personalized coaching — everything you need to get hired faster.

Related Articles