
Master core java fundamentals and spring boot interview topics with real-world questions, explanations, and examples covering oops, collections, streams, multithreading, memory management, and microservices.
Explain how the Liskov Substitution Principle requires substituting a superclass with a subclass without breaking behavior, illustrated by birds, sparrows, and ostriches and the flying capability.
Explore composition and aggregation as has-a relationships with strong and weak lifecycles, contrast with inheritance as an is-a relationship, learn to reuse functionality via composition or aggregation to reduce coupling.
Explain why Java disallows multiple inheritance of classes due to the diamond problem, and how interfaces enable safe multiple inheritance by forcing explicit method overrides to resolve ambiguity.
Explain covariant return types in Java and how a subclass can override a method to return a more specific type, improving type safety and API clarity.
Explain method hiding and method overriding in Java, showing how overriding uses dynamic polymorphism for instance methods at runtime, while hiding applies to static methods at compile time.
Explore how the final keyword controls variables, methods, and classes—making variables constants, preventing overriding, and blocking inheritance and runtime polymorphism. Use final for security, immutability, and potential performance benefits.
Grasp the equals and hashCode contract and how misusing them causes subtle bugs in hash-based collections like HashMap and HashSet. Override both together and use immutable fields for equality.
Explain that finally must accompany a try block and cannot exist without one, with or without a catch block, and that using finally without a try triggers a compilation error.
Explain how the load factor in HashMap governs when to resize, covering default 0.75 and capacity 16, threshold 12, and trade-offs of low vs high load factors.
HashSet uses HashMap internally to achieve constant time lookups for basic operations and prevents duplicates by storing elements as HashMap keys with a dummy value.
Understand the contract between equals and hashCode in Java, including that equal objects share a hash code, and see how breaking it causes duplicates, collisions, and degradation in hash-based collections.
learn how to implement a custom hash map by hashing keys, resolving collisions with separate chaining or open addressing, and resizing as the load factor exceeds thresholds.
Learn how to create immutable collections in Java using unmodifiable views, List.of, and collectors.toUnmodifiable. Compare unmodifiable lists with fully immutable collections in Java 9+ and custom options.
Generics in Java collections enforce compile-time type checks, eliminate runtime errors, and reduce casting, while enabling code reuse, improved readability, and compatibility with legacy code across collections and frameworks.
Explain type erasure in Java generics, how bounds and wildcards are erased, and how this affects runtime behavior while preserving compile-time type safety.
Explain design differences between ArrayList and LinkedList, noting ArrayList uses a dynamic array and LinkedList a doubly linked list, and when insertions, deletions, or fetches are O(1) or O(n).
Compare collections.synchronizedList and CopyOnWriteArrayList in threaded environments. SynchronizedList locks the whole list with low memory; CopyOnWriteArrayList copies on writes, enabling fast reads, and use it when reads exceed writes.
Distinguish between checked and unchecked exceptions by defining compile-time versus runtime handling, and learn when to use each, with examples such as IOException and NullPointerException.
Explain how try-with-resources automates closing, eliminating finally blocks, supports multiple resources in proper order, and relies on compiler-generated closable resource classes to call close after the block.
Learn why throwing in a finally block can mask the original exception and how to handle errors properly by logging and preserving the original exception.
Never catch error or out of memory error, as they signal issues that cannot be handled by the application, causing unpredictable behavior. Catching them masks underlying problems like memory leaks.
Explain how Java exceptions affect Spring transactions, including unchecked vs checked rollback behavior, transactional annotation defaults, rollbackFor and noRollbackFor, and how proxies and boundary placement impact rollback.
Handle uncaught exceptions in threads with the thread uncaught exception handler interface, using per-thread or global defaults to define custom logic when a thread terminates and to ease debugging.
Explore how Spring handles exceptions in controllers with exception handler annotation and controller advice annotation, including Rest controller advice, and tailor responses using response entity exception handler and response status.
Propagates the primary exception from the try block in a try-with-resources block, while suppressed exceptions from closing resources are captured and retrievable via getSuppressed.
Demonstrate how throw without an argument inside a catch block rethrows the caught exception, preserving its stack trace, and compare it with throwing a new exception for logging.
Explain the JVM memory split: young generation holds short-lived objects, old generation holds long-lived objects, metaspace stores class metadata outside the heap. Note minor GC vs major GC.
Explain how Java garbage collection reclaims heap memory with mark-and-sweep, generational GC (young and old generations), and various collectors, including G1 GC region-based, most-garbage-first approach.
Explore the JVM memory structure, including the heap (with the young generation), metaspace outside the heap, per-thread stacks, and the code cache for JIT-compiled code.
Explore how memory leaks arise in Java despite automatic garbage collection when objects retain references, causing memory growth and performance degradation, and learn how to identify and debug them.
Monitor heap growth and gc to detect memory leaks; generate heap dumps with jmap or jvisualvm and analyze with eclipse memory analyzer; fix by removing static references and deregistering listeners.
Examine soft, weak, and phantom references and their roles in memory management. See how strong references block garbage collection while soft and weak references enable caching and finalization tracking.
When a thread allocates more stack memory than available, a stack overflow error occurs. Prevent it by avoiding infinite recursion, adding a base case, and using iteration when possible.
Explore how map and flatMap differ in Java streams by contrasting 1-to-1 transformations with 1-to-many flattening, illustrated with uppercase mapping and flattening a list of lists.
Explain how intermediate operations like filter, map, and flatMap are lazy, transforming a stream into a pipeline that defers processing until a terminal operation triggers execution and produces a result.
Filter retains elements matching a predicate, such as even numbers. Find any and find first are terminal; find any may ignore order in parallel streams, while find first preserves order.
Explore strategies to handle checked exceptions in Java 8 streams or lambdas, including wrapping into runtime exceptions, wrapper utilities, optional handling, and logging to continue the pipeline.
Discover how streams in Java 8 handle large datasets efficiently through lazy evaluation, terminal operations like find first or limit, and parallel streams that minimize memory and CPU usage.
Explore the four major types of method references in Java 8—static, instance of a particular object, instance of an arbitrary object of a type, and constructor—as shorthand for lambdas.
Java lambda expressions can capture final or effectively final local variables, but not those that change after capture; the compiler enforces finality and reports errors when modified.
Compare predicate, function, and supplier in Java eight by highlighting their purposes. Predicate tests boolean conditions, function transforms input to output, and supplier provides values without input.
Explore the spliterator interface, its role in traversing and partitioning data sources for parallel or sequential processing, and how try advance, try split, and for-each-remaining enable stream-like operations.
Learn how to implement a custom function interface with a single abstract method, optional annotation, and default or static methods, using lambda expression to add two variables and log result.
Explain the difference between stateful and stateless intermediate operations in streams, with map, flatMap, and filter as stateless examples and limit, distinct, and sorted as stateful.
Learn how default methods in interfaces provide backward-compatible enhancements in Java 8, enabling new methods without breaking existing implementations, alongside static interface methods that ease API evolution.
Explore functional interfaces in Java eight: predicate for boolean conditions used in filtering and validation, supplier for lazy evaluation and factories, and consumer for actions without a return.
Explore the key components of a lambda expression—the parameter list, arrow, and body—how types are inferred, and how lambdas map to functional interfaces with a concrete addition example.
Explore how this behaves differently in a lambda expression versus an anonymous class: the lambda uses the enclosing instance, while the anonymous class creates a new scope and instance.
Override a default interface method by implementing the interface, providing a custom implementation, and, if needed, calling the default via the interface name dot super dot method to resolve conflicts.
A class implementing two interfaces with the same default method triggers a compiler ambiguity error; override the conflicting method to provide a concrete implementation and resolve the conflict.
Explore how a default method can call other methods in the same interface, including abstract and static methods, enabling modularity, composability, and reusable logic.
Examine the limitations of default methods in interfaces versus class inheritance, including no instance variables or constructors, and limited super usage and final private methods.
Explore thread, runnable, and callable differences and learn when to use each, including extending the thread class and overriding run, and submitting callable to executor service to obtain a future.
Compare synchronized blocks and reentrant locks in Java, highlighting automatic unlock and simple use for synchronized blocks versus explicit, interruptible locking with tryLock and timeouts in ReentrantLock.
Compare countdownlatch and cyclic barrier: countdownlatch waits for a count, cyclic barrier releases when all threads reach the barrier. Use countdownlatch for one-time waits, cyclic barrier for reusable phase coordination.
Explain the differences between sequential and parallel streams in Java 8, including single-thread versus multi-thread execution and when to use each for large data and CPU bound processing.
Use ForkJoinPool for divide-and-conquer tasks with work stealing, breaking large work into subtasks recursively and joining results, unlike ExecutorService, which handles independent tasks without built-in split or join.
Differentiate concurrency and parallelism: concurrency interleaves tasks on one or more threads, while parallelism runs tasks simultaneously on multiple cores. Handle web requests concurrently; process images with parallelism.
Volatile is a field-level modifier that guarantees visibility across threads but does not guarantee thread safety. Synchronized provides atomicity, visibility, and mutual exclusion with locking, making it heavier than volatile.
Contrast deadlock and livelock: deadlock blocks threads forever on locks, while livelock keeps them active but looping without progress, and backoff with random delays helps avoid it.
Explain the purpose of concurrent hash map for thread safe, high performance access in multithreaded environments, noting no null keys and finer grained locking over hash map and synchronized map.
Understand how the thread local class gives each thread its own copy of a variable. See why this avoids synchronization and why removing it in thread pools prevents memory leaks.
Define a functional interface as a single abstract method, optionally annotate with @FunctionalInterface, allow default or static methods, and use lambda expressions to implement it.
Explore Java eight streams, where intermediate operations like filter and map lazily build a pipeline and terminal operations like collect eagerly trigger processing, producing a result and preventing stream reuse.
Explain method references and constructor references as compact shortcuts for lambda expressions, with syntax using ClassName::method, ClassName::new, and examples like Math::abs, System.out::println, String::toLowerCase, and ArrayList::new to improve code readability.
Explore default methods in interfaces and their role in backward compatibility, enabling interfaces to include concrete methods in Java 8 for evolving interfaces without breaking existing code.
When two Java interfaces share a default method and a class implements both, override the method to resolve conflict, and call the interface default via super, addressing the diamond problem.
Learn how static methods in interfaces provide interface-specific utilities and encapsulation, callable only through the interface name. See examples like comparator.comparing and predicate.isEqual as static methods in functional interfaces.
Explore java.util.function's core interfaces—predicate, function, consumer, and supplier—covering boolean tests, one-argument mappings, actions, no-argument value supplies, and bi-functional variants for two inputs.
Explore how findFirst, findAny, anyMatch, and allMatch work in Java streams, comparing encounter order, determinism in sequential versus parallel streams, and predicate results.
Use Java 8's Optional to avoid null pointer exceptions by wrapping values with Optional.of or Optional.ofNullable and providing defaults. Apply safe chaining for nested fields to prevent runtime crashes.
Explore the difference between map and flatMap in streams, showing 1-to-1 transformation versus flattening nested structures, with practical examples of mapping strings to lengths and flattening lists.
Explore the spliterator in Java 8, an advanced, parallel-ready iterator that splits data structures for parallel processing and offers tryAdvance, forEachRemaining, trySplit, and size estimates.
Explore the java.time LocalDate, LocalTime, and LocalDateTime classes introduced in Java 8 to fix issues with the old java.util.date and calendar API, emphasizing immutability, thread safety, and fluent usage.
Learn how Java implements lambdas at runtime using the invokedynamic instruction, the lambda meta factory, and a dynamically created hidden class that implements the functional interface.
Parallel streams split work into subtasks and run on multiple CPU cores, offering speedups for large CPU-bound data sets but incurring overhead from task splitting and thread management.
Explore how sealed classes, abstract classes, and interfaces differ in controlling inheritance, with sealed classes enabling exhaustive modeling, abstract classes providing shared code, and interfaces defining capabilities.
Discover how a sealed class can have final and non-sealed subclasses, with final preventing subclassing and non-sealed enabling unrestricted extensions, as shown with shape, circle, rectangle, square, and polygon.
Learn how pattern matching with instance of in Java 16 integrates type checking and casting, eliminating separate casts, reducing boilerplate, and avoiding class cast exceptions to improve readability and safety.
Java 16 records simplify immutable data classes by auto-generating header, fields, constructors, accessors, and equals, hashCode, toString; records are final and not inheritable.
Understand how sealed classes control inheritance: use extends for standard subclassing, and permits to restrict which classes may extend a sealed class, as shown with shape and circle.
Explore text blocks in Java 15, enabling multiline strings with triple double quotes to improve readability, format HTML, JSON, SQL, and XML, and reduce escape sequences for maintainability.
Java 14 introduced switch expressions, making switch statements concise, safer, and able to return values. They avoid fall through, support yield, and can be used in assignments, unlike traditional switches.
Discover the Java 11 http client API, a modern asynchronous and synchronous replacement for http url connection, with fluent, chainable design, built in body handlers, and web socket support.
Explore how the lines method in Java, introduced in Java eight, reads lines from files or strings via a lazy, memory-efficient stream, with use cases like filtering and mapping lines.
Understand Java 10's var for local variable type inference, deducing types from initializers, useful for streams and lambdas; use only for locals—not fields or parameters, when types are obvious.
List.copyOf creates a new immutable list via a shallow copy, rejecting null elements, while Collections.unmodifiableList wraps the original list to provide an immutable view without copying.
Explore how requires, exports, and opens govern module dependencies, visibility, and reflection in the Java module system, via module-info.java, exposing packages and enabling reflective access for frameworks.
Learn how Java nine's List.of, Set.of, and Map.of create immutable collections concisely. They disallow nulls, prevent modification, and enforce uniqueness for sets and maps.
Explain dependency injection in Spring, including constructor, setter, and field injection, with field injection discouraged, and show how the Spring IOC container manages beans via component scanning and autowiring.
The difference between @Autowired and @Inject lies in origin—spring specific versus java standard—yet they share default required behavior and the qualifier annotation, with @Autowired supporting required as false.
Enable auto configuration automatically creates beans based on classpath and properties, reducing boilerplate. It uses the Spring Boot application annotation, import selector, Spring factories, and conditional annotations to tailor beans.
Spring Boot optimizes dependency injection by auto-configuring beans through convention-based conditional configurations, using conditional on class, conditional on missing bean, and component scanning to inject dependencies only as needed.
Explore how Spring Boot application annotation acts as a meta annotation, combining configuration, enable auto configuration, and component scan to bootstrap beans in the Spring container for dependency injection.
Explain how the primary annotation sets a default bean and how the qualifier overrides it to select a specific bean when multiple candidates exist.
design a multi-module spring boot app with clear module boundaries and dependency injection via interfaces; organize modules as common, domain, persistence, service, web, and app, with component scanning and testing.
Explain the difference between configuration and component annotations for beans: configuration ensures singleton via proxying; component marks classes for scanning and may create new instances on internal calls; use accordingly.
Explore Spring bean scopes including singleton, prototype, request, session, application, and WebSocket, with definitions, lifecycles, and practical use cases.
Compare application.properties and application.yml in Spring Boot, noting that properties use single-line key-value pairs while YAML supports hierarchical data and profiles enable environment-specific configurations.
Spring Boot binds external configuration values to a Java bean using configuration properties by mapping app prefix properties from properties, YAML, env vars, or command line arguments into a POJO.
Are you preparing for your next Java developer interview and feeling a bit unsure about the kinds of questions you might face? Don’t worry — you’re not alone! Whether you're a fresher stepping into your very first interview or an experienced developer looking to take the next big leap in your career, this course is your ultimate companion to help you crack Java interviews with clarity and confidence.
In "Must Java Developer Interview Questions and Answers," we’ve handpicked and curated the most frequently asked and important interview questions based on real-world interviews from top tech companies like Infosys, TCS, Accenture, and more. Each question is carefully broken down with clear, detailed explanations, coding examples, and real-life scenarios so that you're not just memorising answers — you’re truly understanding the concepts and learning how to apply them in real interview settings.
We’ll cover everything from Java basics to advanced topics like OOPs, Collections, Multithreading, Java 8 features, Exception Handling, and even tricky logic-based questions that often stump candidates. Plus, you’ll get bonus tips on give interviews with confidence if you opt for mock interviews that I conduct free of charge.
By the end of this course, you'll feel prepared, confident, and interview-ready. Let's get started!