CODERBLUEPRINT
JAVA • SPRING BOOT •
MICROSERVICES
The Complete Interview Preparation Guide
140+ Real Interview Questions & Answers, Coding Problems, and System Design Concepts
Table of Contents
1. Java Memory Management
2. Java Streams API
3. Java 8 Features
4. Comparable vs Comparator
5. Collections Framework, HashMap Internals & equals/hashCode
6. LFU Cache Implementation
7. Fail-Fast vs Fail-Safe Collections
8. Thread-Safe Collections
9. Coding Questions - Strings, Sorting, HashMap, LinkedList
10. ArrayList vs LinkedList
11. Cloning and Copy Constructor
12. Design Patterns - Singleton, Builder, Chain of Responsibility, Adapter
13. Spring Boot - Annotations, REST, Exception Handling & @Transactional
14. JPA, Hibernate & Database Locking
15. Asynchronous Processing in Spring (@Async)
16. ExecutorService - Deep Dive
17. Microservices - Types, Communication, Circuit Breaker & JWT
18. Spring Security
19. AWS Services (commonly asked for Java/Spring Boot roles)
20. Apache Kafka - Topics, Producers, Consumer Groups & Idempotency
21. General / Frequently Asked Core Java Questions
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
1. Java Memory Management
Q1. How does memory management work in Java (JVM Memory Model)?
Java memory is managed automatically by the JVM through the Garbage Collector, so developers rarely
allocate or free memory manually. When the JVM starts, it reserves a block of memory from the OS and
divides it into several runtime areas.
bullet
Heap - stores all objects and arrays; shared across threads; managed by the Garbage Collector.
bullet
Stack - one per thread; stores method call frames, local variables, and partial results; entries are
pushed/popped as methods are called and return.
bullet
Method Area / Metaspace (Java 8+) - stores class metadata, static variables, constant pool, and
method bytecode. Metaspace lives in native (off-heap) memory, not the JVM heap.
bullet
PC Register - holds the address of the currently executing instruction, per thread.
bullet
Native Method Stack - supports native (JNI) method calls.
When an object has no more reachable references, it becomes eligible for Garbage Collection, and the GC
reclaims that memory in the background.
Q2. What is Heap memory in Java?
Heap is the runtime data area where all Java objects and arrays are allocated. It is created when the JVM
starts and is shared by all threads of the application. Its size can be tuned using -Xms (initial size) and -Xmx
(maximum size).
bullet
Young Generation - split into Eden and two Survivor spaces (S0, S1); new objects are created here;
minor GC runs frequently and is fast.
bullet
Old (Tenured) Generation - objects that survive multiple minor GC cycles are promoted here; major/full
GC runs less often but is more expensive.
bullet
(Pre-Java 8) PermGen used to store class metadata; replaced by Metaspace in Java 8 which grows in
native memory instead of a fixed heap region.
Q3. Where are objects and static variables stored in Java?
Objects (created with 'new') are always stored on the Heap, regardless of whether the reference variable is a
local variable or an instance variable. Only the reference (pointer) to the object may live on the Stack (if it's a
local variable) or inside another object on the Heap (if it's an instance field).
Static variables belong to the class, not to any instance, so they are stored in the Method Area / Metaspace,
and only one copy exists per classloader regardless of how many objects are created.
Local primitive variables and references live on the Stack frame of the method call and are removed
automatically once the method returns.
2. Java Streams API
Q4. What is the Stream API and how is it different from Collections?
A Stream is a sequence of elements that supports functional-style, declarative operations (map, filter, reduce,
etc.) instead of external iteration. Streams don't store data - they operate on a source (Collection, array, I/O
channel) and produce a result without modifying the source.
Page 3 | coderblueprint
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
bullet
Lazy evaluation - intermediate operations (map, filter) are not executed until a terminal operation
(collect, forEach, reduce) is invoked.
bullet
Can be used only once - once a terminal operation runs, the stream is consumed.
bullet
Supports parallel execution via .parallelStream() using the ForkJoin common pool.
bullet
Intermediate ops: map, filter, sorted, distinct, limit, skip, flatMap. Terminal ops: collect, forEach, reduce,
count, anyMatch/allMatch.
Q5. Difference between map() and flatMap()?
map() transforms each element into exactly one new element (1-to-1), producing a Stream<Stream<T>> if
the mapper returns a stream. flatMap() transforms each element into a stream and then flattens all those
streams into a single stream (1-to-many), which is essential when dealing with nested collections like
List<List<String>>.
Q6. Coding: Find the second highest salary of an Employee using Streams.
Sort employees by salary descending, skip the first (highest), then take the first remaining - or use distinct()
first if duplicate salaries should be treated as one rank.
List<Employee> employees = ...;
Optional<Employee> secondHighest = [Link]()
.sorted([Link](Employee::getSalary).reversed())
.distinct() // by equals()/hashCode() - or use a key extractor
.skip(1)
.findFirst();
// Cleaner: dedupe strictly by salary value
Optional<Double> secondHighestSalary = [Link]()
.map(Employee::getSalary)
.distinct()
.sorted([Link]())
.skip(1)
.findFirst();
Q7. Coding: Find the first non-repeating (unique) character in a string using Streams.
Build a frequency map with groupingBy + counting, then stream the characters in original order and find the
first one whose count is 1 - preserving order requires a LinkedHashMap.
String input = "swiss";
Map<Character, Long> freq = [Link]()
.mapToObj(c -> (char) c)
.collect([Link](c -> c, LinkedHashMap::new, [Link]()));
Character firstUnique = [Link]().stream()
.filter(e -> [Link]() == 1)
.map([Link]::getKey)
.findFirst()
.orElse(null); // 'w'
Q8. Coding: Sort a list/array of integers or strings using Streams.
Use .sorted() for natural order or pass a Comparator for custom ordering; sorted() returns a new stream, the
original list is untouched.
List<Integer> nums = [Link](5, 3, 8, 1, 9);
List<Integer> ascending = [Link]().sorted().collect([Link]());
Page 4 | coderblueprint
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
List<Integer> descending = [Link]()
.sorted([Link]())
.collect([Link]());
// Sort strings by length, then alphabetically
List<String> words = [Link]("pen","apple","cat","banana");
List<String> sorted = [Link]()
.sorted([Link](String::length).thenComparing([Link]()))
.collect([Link]());
Q9. What is the difference between [Link](), groupingBy() and
partitioningBy()?
toList() simply gathers stream elements into a List. groupingBy() classifies elements into a Map keyed by a
classifier function (like SQL GROUP BY), useful when there are more than two groups - e.g. grouping
employees by department. partitioningBy() is a special case that always produces exactly two groups keyed
by true/false based on a predicate - e.g. splitting employees into 'salary > 50000' and the rest.
Q10. What is the difference between findFirst() and findAny()?
findFirst() always returns the first element of the encounter order and is deterministic even in a parallel
stream. findAny() returns any matching element and is allowed to return a different one on every run in a
parallel stream because it's optimized for performance, not for order guarantees.
Q11. What is a Collector and can you write a custom one?
A Collector is a reduction operation defined by four functions - a supplier (creates the result container), an
accumulator (adds an element to it), a combiner (merges two containers, used in parallel streams), and a
finisher (final transformation). [Link](...) lets you build a custom collector, though most use cases are
covered by the built-in Collectors class (toList, toMap, joining, groupingBy, summarizingInt, etc.).
3. Java 8 Features
Q12. What are the major features introduced in Java 8?
bullet
Lambda Expressions - concise syntax for implementing functional interfaces, e.g. (a, b) -> a + b.
bullet
Functional Interfaces - interfaces with a single abstract method (Runnable, Comparator);
[Link] package added Function, Predicate, Supplier, Consumer, BiFunction, etc.
bullet
Stream API - declarative, pipeline-based processing of collections.
bullet
Default and Static methods in interfaces - allows adding new methods to interfaces without breaking
existing implementations.
bullet
Optional<T> - a container object to avoid NullPointerException and force explicit handling of 'value may
be absent'.
bullet
New Date/Time API ([Link]) - LocalDate, LocalDateTime, ZonedDateTime, Duration, Period -
immutable and thread-safe, replacing the flawed [Link]/Calendar.
bullet
Method References - shorthand for lambdas that just call an existing method, e.g. String::toUpperCase.
bullet
Nashorn JavaScript Engine (removed later in Java 15).
Q13. What is a functional interface? Give examples.
Page 5 | coderblueprint
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
A functional interface has exactly one abstract method (it can have any number of default/static methods)
and can be marked with @FunctionalInterface for compile-time checking. It is the target type for a lambda
expression.
bullet
Runnable - run()
bullet
Comparator<T> - compare(T,T)
bullet
Function<T,R> - apply(T)
bullet
Predicate<T> - test(T)
bullet
Supplier<T> - get()
bullet
Consumer<T> - accept(T)
Q14. What is Optional and why was it introduced?
Optional<T> is a wrapper that either contains a non-null value or is empty, forcing callers to explicitly handle
the 'no value' case instead of silently risking a NullPointerException. Common methods: isPresent(),
ifPresent(), orElse(), orElseGet(), orElseThrow(), map(), flatMap(). Best practice: use it as a method return
type, not as a field or method parameter.
Q15. Default vs Static methods in interfaces?
A default method provides a body inside an interface and can be overridden by implementing classes; it was
introduced so existing interfaces (like List) could add new methods (like forEach, stream) without breaking
every class that already implements them. A static method belongs to the interface itself, cannot be
overridden, and is called directly on the interface name, e.g. [Link](...).
4. Comparable vs Comparator
Q16. Difference between Comparable and Comparator?
bullet
Comparable is implemented by the class itself (compareTo method) and defines the object's single
'natural ordering', e.g. Employee implements Comparable<Employee>.
bullet
Comparator is a separate class/lambda (compare method) that defines external, custom ordering, and
you can create many different Comparators for the same class without modifying it.
bullet
Comparable -> [Link], one sorting sequence per class. Comparator -> [Link], unlimited sorting
sequences.
bullet
Comparator supports composing rules:
[Link](Employee::getDept).thenComparing(Employee::getSalary,
[Link]()).
// Comparable
class Employee implements Comparable<Employee> {
int salary;
public int compareTo(Employee o) { return [Link]([Link], [Link]); }
}
// Comparator
List<Employee> list = ...;
[Link]([Link](Employee::getSalary).reversed()
.thenComparing(Employee::getName));
Page 6 | coderblueprint
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
5. Collections Framework, HashMap Internals &
equals/hashCode
Q17. Explain the Java Collections Framework hierarchy.
bullet
Collection -> List (ArrayList, LinkedList, Vector), Set (HashSet, LinkedHashSet, TreeSet), Queue
(PriorityQueue, ArrayDeque).
bullet
Map is a separate hierarchy (not a Collection) -> HashMap, LinkedHashMap, TreeMap, Hashtable,
ConcurrentHashMap.
bullet
List allows duplicates and maintains insertion order via index; Set disallows duplicates; Map stores
key-value pairs with unique keys.
Q18. How does HashMap work internally?
A HashMap stores entries in an array of buckets. To insert a key, it computes hash([Link]()) (an
additional hash spreading function is applied to reduce clustering), then maps that hash to a bucket index
using (n-1) & hash where n is the array length (always a power of two). The entry (key, value, hash, next) is
placed in that bucket.
Default capacity is 16 with a load factor of 0.75; once size exceeds capacity * loadFactor, the internal array is
resized (doubled) and all entries are rehashed - this is called resizing/rehashing.
Since Java 8, if a single bucket's linked list grows beyond 8 entries (and table capacity >= 64), that bucket is
converted into a Red-Black Tree, changing worst-case lookup from O(n) to O(log n).
Q19. What is a HashMap collision and how is it handled?
A collision happens when two different keys produce the same bucket index (same hash & (n-1)), even if
their hashCode() values differ, because multiple hash values can map to the same bucket.
bullet
Java 7 and earlier: collisions are handled via chaining - a linked list of entries is stored per bucket; a
colliding entry is appended to the list.
bullet
Java 8+: still uses a linked list initially, but if a bucket's chain length exceeds TREEIFY_THRESHOLD
(8) and the table has at least 64 buckets, the list is converted to a self-balancing Red-Black tree for that
bucket, improving worst-case get/put from O(n) to O(log n).
bullet
On lookup, once the correct bucket is found, equals() is used to distinguish between the colliding keys
to find the exact match.
Q20. What is the relationship between equals() and hashCode()?
The general contract (from Object class) is: if two objects are equal according to equals(), they MUST have
the same hashCode(). The reverse is not required - two unequal objects can share a hashCode (that's
exactly a hash collision).
If you override equals() but not hashCode() (or vice versa), you break this contract, and hash-based
collections (HashMap, HashSet, HashTable) will behave incorrectly - e.g. two 'equal' objects could end up in
different buckets, so [Link](key) might return null even though an 'equal' key was inserted earlier.
Best practice: always override both together, and use the same fields in both methods (IDEs and Lombok's
@EqualsAndHashCode automate this).
Q21. Difference between HashMap, LinkedHashMap and TreeMap?
bullet
HashMap - no ordering guarantee, O(1) average get/put, allows one null key and multiple null values.
Page 7 | coderblueprint
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
bullet
LinkedHashMap - maintains insertion order (or access order if configured) using an internal doubly
linked list; useful for building an LRU cache.
bullet
TreeMap - maintains keys in sorted order (natural or via Comparator), backed by a Red-Black tree,
O(log n) get/put; does not allow null keys.
6. LFU Cache Implementation
Q22. Design and implement an LFU (Least Frequently Used) Cache.
An LFU cache evicts the entry with the smallest access frequency when it's full; on a tie, the least recently
used among those is evicted. An O(1) implementation uses three structures:
bullet
keyToValFreq: Map<Key, Node> - key -> (value, frequency)
bullet
freqToKeys: Map<Integer, LinkedHashSet<Key>> - frequency -> ordered set of keys at that frequency
(LinkedHashSet keeps insertion/access order for tie-breaking)
bullet
minFreq: tracks the current minimum frequency in the cache for O(1) eviction
class LFUCache {
private final int capacity;
private int minFreq;
private final Map<Integer, int[]> keyToValFreq = new HashMap<>(); // key -> {value, freq}
private final Map<Integer, LinkedHashSet<Integer>> freqToKeys = new HashMap<>();
public LFUCache(int capacity) {
[Link] = capacity;
}
public int get(int key) {
if () return -1;
bumpFrequency(key);
return [Link](key)[0];
}
public void put(int key, int value) {
if (capacity <= 0) return;
if ([Link](key)) {
[Link](key)[0] = value;
bumpFrequency(key);
return;
}
if ([Link]() >= capacity) {
int evictKey = [Link](minFreq).iterator().next();
[Link](minFreq).remove(evictKey);
[Link](evictKey);
}
[Link](key, new int[]{value, 1});
[Link](1, k -> new LinkedHashSet<>()).add(key);
minFreq = 1;
}
private void bumpFrequency(int key) {
int freq = [Link](key)[1];
[Link](freq).remove(key);
if ([Link](freq).isEmpty()) {
[Link](freq);
if (minFreq == freq) minFreq++;
}
[Link](key)[1] = freq + 1;
Page 8 | coderblueprint
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
[Link](freq + 1, k -> new LinkedHashSet<>()).add(key);
}
}
Q23. How would you implement an LRU Cache quickly (commonly asked alongside
LFU)?
The simplest production-ready way is to extend LinkedHashMap with access-order enabled and override
removeEldestEntry().
class LRUCache<K,V> extends LinkedHashMap<K,V> {
private final int capacity;
LRUCache(int capacity) {
super(capacity, 0.75f, true); // true = access-order
[Link] = capacity;
}
@Override
protected boolean removeEldestEntry([Link]<K,V> eldest) {
return size() > capacity;
}
}
7. Fail-Fast vs Fail-Safe Collections
Q24. What is the difference between Fail-Fast and Fail-Safe collections?
bullet
Fail-Fast: iterators operate directly on the original collection and throw ConcurrentModificationException
immediately if the collection is structurally modified while iterating (except via the iterator's own
remove()). Detected using an internal modCount counter compared on each next() call. Examples:
ArrayList, HashMap, HashSet.
bullet
Fail-Safe: iterators operate on a clone/snapshot of the collection (or use copy-on-write), so concurrent
modification during iteration doesn't throw an exception - though the iterator may not reflect the latest
changes. Examples: CopyOnWriteArrayList, ConcurrentHashMap.
bullet
Trade-off: fail-safe avoids exceptions but costs extra memory (for the snapshot/copy) and can give you
slightly stale data.
8. Thread-Safe Collections
Q25. What are the ways to make a collection thread-safe in Java?
bullet
Legacy synchronized wrappers: [Link]/Map/Set(...) - wraps every method call
with a single lock, so it's correct but has poor concurrency (whole collection is locked).
bullet
Concurrent collections ([Link]) - purpose-built for high concurrency: ConcurrentHashMap
(segmented/bucket-level locking), CopyOnWriteArrayList / CopyOnWriteArraySet (good for read-heavy,
rarely-written lists), ConcurrentLinkedQueue (lock-free, non-blocking), BlockingQueue implementations
(ArrayBlockingQueue, LinkedBlockingQueue) for producer-consumer patterns.
bullet
Legacy classes that are inherently synchronized: Vector, Hashtable (rarely used today, slower than
ConcurrentHashMap).
Page 9 | coderblueprint
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
Q26. How does ConcurrentHashMap achieve thread safety without locking the whole
map?
In Java 7, ConcurrentHashMap divided the map into a fixed number of segments, each with its own lock, so
different threads could write to different segments concurrently. From Java 8 onward, segment locking was
removed; instead it locks only the individual bucket (the head node of a bin) during a write using
synchronized blocks combined with CAS (Compare-And-Swap) operations for the common case, giving
much finer-grained concurrency. Reads are largely lock-free thanks to volatile reads on the table.
9. Coding Questions - Strings, Sorting, HashMap,
LinkedList
Q27. Reverse a String / check if a String is a Palindrome.
String reversed = new StringBuilder(str).reverse().toString();
boolean isPalindrome(String s) {
int i = 0, j = [Link]() - 1;
while (i < j) {
if ([Link](i++) != [Link](j--)) return false;
}
return true;
}
Q28. Check if two Strings are Anagrams of each other.
boolean isAnagram(String a, String b) {
if ([Link]() != [Link]()) return false;
int[] freq = new int[256];
for (char c : [Link]()) freq[c]++;
for (char c : [Link]()) freq[c]--;
for (int f : freq) if (f != 0) return false;
return true;
}
Q29. Find duplicate elements in an array using HashMap/HashSet.
List<Integer> findDuplicates(int[] arr) {
Set<Integer> seen = new HashSet<>();
List<Integer> duplicates = new ArrayList<>();
for (int n : arr) {
if () [Link](n);
}
return duplicates;
}
Q30. Reverse a Singly Linked List (iterative).
Node reverse(Node head) {
Node prev = null, curr = head;
while (curr != null) {
Node next = [Link];
[Link] = prev;
prev = curr;
curr = next;
Page 10 | coderblueprint
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
}
return prev; // new head
}
Q31. Detect a Cycle in a Linked List (Floyd's Tortoise and Hare).
boolean hasCycle(Node head) {
Node slow = head, fast = head;
while (fast != null && [Link] != null) {
slow = [Link];
fast = [Link];
if (slow == fast) return true;
}
return false;
}
Q32. Merge two sorted arrays / implement a merge sort by hand.
void merge(int[] a, int[] b, int[] result) {
int i = 0, j = 0, k = 0;
while (i < [Link] && j < [Link]) {
result[k++] = (a[i] <= b[j]) ? a[i++] : b[j++];
}
while (i < [Link]) result[k++] = a[i++];
while (j < [Link]) result[k++] = b[j++];
}
10. ArrayList vs LinkedList
Q33. Difference between ArrayList and LinkedList?
bullet
Internal structure: ArrayList uses a dynamically resizable array; LinkedList uses a doubly linked list of
nodes.
bullet
Random access: ArrayList get(index) is O(1); LinkedList get(index) is O(n) since it must traverse from
head or tail.
bullet
Insertion/Deletion: at the beginning or middle, LinkedList is O(1) once you have the node reference (no
shifting), while ArrayList is O(n) due to shifting elements. At the end, both are effectively O(1)
amortized.
bullet
Memory: ArrayList has lower per-element overhead; LinkedList needs extra memory per node for two
pointers (prev/next).
bullet
Use ArrayList by default (better cache locality, faster iteration); use LinkedList only when you need
frequent insertions/deletions at both ends (it also implements Deque).
11. Cloning and Copy Constructor
Q34. What is Object cloning in Java? Shallow vs Deep copy?
Cloning creates a duplicate of an object using the clone() method inherited from Object, after implementing
the marker interface Cloneable (calling clone() without implementing Cloneable throws
CloneNotSupportedException).
Page 11 | coderblueprint
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
bullet
Shallow copy (default [Link]()) - copies primitive fields directly, but for reference fields it copies
only the reference, so the clone and original share the same nested objects.
bullet
Deep copy - recursively clones nested/mutable objects too, so the clone is fully independent; typically
implemented manually by overriding clone() to also clone each mutable field, or via serialization, or a
copy constructor.
Q35. What is a Copy Constructor and how does it compare to clone()?
A copy constructor is a regular constructor that takes another object of the same class and copies its fields,
e.g. public Employee(Employee other) { [Link] = [Link]; ... }. It is generally preferred over clone()
because it doesn't require implementing Cloneable, doesn't throw a checked exception, gives full control over
deep vs shallow copying, and works cleanly with final fields (clone() can't easily set final fields since it
bypasses the constructor).
12. Design Patterns - Singleton, Builder, Chain of
Responsibility, Adapter
Q36. Implement a thread-safe Singleton (Bill Pugh / double-checked locking).
The Bill Pugh Singleton (static inner holder class) is the most recommended approach - it's lazy-loaded,
thread-safe without explicit synchronization, and relies on the JVM's classloading guarantees.
public class Singleton {
private Singleton() {}
private static class Holder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return [Link];
}
}
// Double-checked locking alternative
public class Singleton2 {
private static volatile Singleton2 instance;
private Singleton2() {}
public static Singleton2 getInstance() {
if (instance == null) {
synchronized ([Link]) {
if (instance == null) {
instance = new Singleton2();
}
}
}
return instance;
}
}
Q37. How can a Singleton be broken, and how do you prevent it?
bullet
Reflection - can call the private constructor directly; prevent by throwing an exception inside the
constructor if an instance already exists.
Page 12 | coderblueprint
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
bullet
Serialization - deserializing creates a new instance; prevent by implementing readResolve() to return
the existing instance.
bullet
Cloning - clone() can create a second instance; prevent by overriding clone() to throw
CloneNotSupportedException.
bullet
The safest approach that resists all three is an Enum-based Singleton, since enums are inherently
serialization-safe and reflection-proof.
Q38. Implement the Builder pattern.
Builder is used to construct complex objects step by step, especially when a class has many optional fields,
avoiding 'telescoping constructors'. It typically uses a static nested Builder class with fluent setters returning
'this', and a private constructor on the outer class that takes the Builder.
public class Employee {
private final String name;
private final int age;
private final String department; // optional
private Employee(Builder b) {
[Link] = [Link];
[Link] = [Link];
[Link] = [Link];
}
public static class Builder {
private String name;
private int age;
private String department;
public Builder name(String name) { [Link] = name; return this; }
public Builder age(int age) { [Link] = age; return this; }
public Builder department(String d) { [Link] = d; return this; }
public Employee build() { return new Employee(this); }
}
}
// Usage
Employee e = new [Link]().name("Ravi").age(28).department("Engineering").build();
Q39. Explain the Chain of Responsibility pattern with an example.
Chain of Responsibility passes a request along a chain of handler objects; each handler decides either to
process the request or pass it to the next handler in the chain. This decouples the sender of a request from
its receivers. It is used heavily in Java's Servlet Filter chains and Spring Security's FilterChain.
abstract class Approver {
protected Approver next;
void setNext(Approver next) { [Link] = next; }
abstract void approve(int amount);
}
class Manager extends Approver {
void approve(int amount) {
if (amount <= 1000) [Link]("Manager approved");
else if (next != null) [Link](amount);
}
}
class Director extends Approver {
void approve(int amount) {
Page 13 | coderblueprint
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
if (amount <= 5000) [Link]("Director approved");
else if (next != null) [Link](amount);
}
}
// [Link](director); [Link](3000);
Q40. Explain the Adapter pattern with an example.
Adapter converts the interface of one class into another interface that a client expects, letting incompatible
interfaces work together - like a real-world power plug adapter. It's commonly used to integrate a legacy class
or a third-party library whose interface doesn't match what your code expects.
interface MediaPlayer { void play(String fileName); }
class LegacyMp4Player { void playMp4(String fileName) { /* legacy logic */ } }
class MediaAdapter implements MediaPlayer {
private LegacyMp4Player mp4Player = new LegacyMp4Player();
public void play(String fileName) {
mp4Player.playMp4(fileName); // adapts the call
}
}
13. Spring Boot - Annotations, REST, Exception
Handling & @Transactional
Q41. Explain the commonly used Spring Boot annotations.
bullet
@SpringBootApplication - combines @Configuration, @EnableAutoConfiguration and
@ComponentScan.
bullet
@RestController = @Controller + @ResponseBody, returns data (JSON/XML) directly instead of a view
name.
bullet
@RequestMapping / @GetMapping / @PostMapping / @PutMapping / @DeleteMapping - map HTTP
requests to handler methods.
bullet
@Autowired - injects a Spring-managed bean by type (constructor injection is now the recommended
style over field injection).
bullet
@Component / @Service / @Repository - stereotype annotations that register a class as a Spring
bean; @Repository additionally translates persistence exceptions into Spring's DataAccessException
hierarchy.
bullet
@Qualifier - resolves ambiguity when multiple beans of the same type exist.
bullet
@Value - injects a property value from [Link]/yml.
bullet
@ConfigurationProperties - binds a whole group of properties to a POJO.
bullet
@RequestParam / @PathVariable / @RequestBody / @RequestHeader - extract data from the
incoming HTTP request.
bullet
@Transactional - wraps a method in a database transaction.
bullet
@ExceptionHandler / @ControllerAdvice - centralized exception handling.
Q42. How do you design REST APIs properly (best practices)?
bullet
Use nouns for resources, not verbs: /employees not /getEmployees.
Page 14 | coderblueprint
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
bullet
Use correct HTTP methods: GET (read), POST (create), PUT (full update), PATCH (partial update),
DELETE (remove).
bullet
Use proper status codes: 200 OK, 201 Created, 204 No Content, 400 Bad Request, 401 Unauthorized,
403 Forbidden, 404 Not Found, 409 Conflict, 500 Internal Server Error.
bullet
Version your APIs (/api/v1/...), support pagination/filtering/sorting via query params, and keep
responses consistent using a common response wrapper/DTO.
Q43. How is exception handling done in Spring Boot?
Spring Boot centralizes exception handling using @ControllerAdvice combined with @ExceptionHandler, so
you don't need try-catch blocks scattered across every controller. A global handler class intercepts
exceptions thrown by any controller and converts them into a consistent error response (often a custom
ErrorResponse DTO with status, message, timestamp).
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler([Link])
public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException ex) {
ErrorResponse err = new ErrorResponse(HttpStatus.NOT_FOUND.value(), [Link]());
return new ResponseEntity<>(err, HttpStatus.NOT_FOUND);
}
@ExceptionHandler([Link])
public ResponseEntity<ErrorResponse> handleGeneric(Exception ex) {
ErrorResponse err = new ErrorResponse(500, "Something went wrong");
return new ResponseEntity<>(err, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Q44. Explain @Transactional in depth - propagation and isolation levels.
@Transactional tells Spring's AOP proxy to wrap a method call in a database transaction, automatically
committing on success or rolling back on a RuntimeException (checked exceptions do NOT trigger rollback
by default unless configured with rollbackFor).
bullet
[Link] (default) - joins an existing transaction, or creates a new one if none exists.
bullet
Propagation.REQUIRES_NEW - always suspends any existing transaction and starts a brand-new
independent one.
bullet
[Link] - runs within a nested transaction (savepoint) inside the existing one; can roll
back independently.
bullet
[Link] / NOT_SUPPORTED / MANDATORY / NEVER - other less common
combinations.
bullet
Isolation levels: READ_UNCOMMITTED, READ_COMMITTED (most common default in
Postgres/Oracle), REPEATABLE_READ (MySQL InnoDB default), SERIALIZABLE (strictest, prevents
phantom reads but hurts concurrency).
bullet
Common pitfall: calling a @Transactional method from another method in the SAME class doesn't go
through the Spring proxy, so the transaction is silently ignored - it must be called from a different
bean/class.
14. JPA, Hibernate & Database Locking
Q45. Difference between JPA and Hibernate?
Page 15 | coderblueprint
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
JPA (Java Persistence API) is just a specification/interface (a set of annotations and interfaces like
EntityManager, @Entity) that defines how ORM should work in Java - it has no implementation of its own.
Hibernate is one of several concrete implementations of the JPA spec (others include EclipseLink,
OpenJPA), and also provides extra Hibernate-specific features beyond the JPA spec (like @NaturalId,
custom types, and a richer Criteria API).
Q46. Explain First-level vs Second-level cache in Hibernate.
bullet
First-level cache - tied to the Hibernate Session/EntityManager, enabled by default, not shared across
sessions; cleared when the session closes.
bullet
Second-level cache - optional, configured at the SessionFactory level, shared across sessions (often
backed by EhCache, Caffeine, or Redis), useful for read-mostly reference data.
Q47. What is the N+1 select problem and how do you fix it?
N+1 happens when fetching a list of N parent entities triggers 1 query for the parents, then N additional
queries (one per parent) to lazily fetch each related child collection - devastating for performance at scale.
bullet
Use JOIN FETCH in JPQL to eagerly fetch the association in a single query.
bullet
Use @EntityGraph to declaratively specify which associations to fetch eagerly for a specific query.
bullet
Enable batch fetching (hibernate.default_batch_fetch_size) so Hibernate fetches related entities in
batches instead of one-by-one.
Q48. Explain Optimistic vs Pessimistic Locking in JPA.
bullet
Optimistic Locking - assumes conflicts are rare; each entity has a @Version column (int/timestamp). On
update, Hibernate checks the version hasn't changed since it was read; if it has, an
OptimisticLockException is thrown. No DB-level lock is held, so it scales better for read-heavy systems.
bullet
Pessimistic Locking - assumes conflicts are likely; acquires an actual database row lock (SELECT ...
FOR UPDATE) at read time via LockModeType.PESSIMISTIC_WRITE/READ, blocking other
transactions from modifying (or even reading, depending on mode) that row until the transaction
completes.
bullet
Use optimistic locking for high-concurrency, low-conflict scenarios (e.g. e-commerce catalog updates);
use pessimistic locking when correctness under heavy contention is critical (e.g. seat booking, bank
balance updates).
Q49. Difference between [Link] and [Link]?
LAZY defers loading an association until it's actually accessed (returns a proxy), reducing unnecessary
queries but risking a LazyInitializationException if accessed outside an open Hibernate session. EAGER
loads the association immediately along with the parent entity, which is simpler but can cause performance
issues and accidental N+1 queries if overused. Best practice: default everything to LAZY and fetch eagerly
only when explicitly needed via JOIN FETCH or @EntityGraph.
15. Asynchronous Processing in Spring (@Async)
Q50. How does @Async work in Spring, and what are its pitfalls?
@Async makes a method execute in a separate thread (from a configured TaskExecutor) instead of blocking
the caller's thread; the method must be public and called from a different bean (proxy limitation, same as
@Transactional). Enable it with @EnableAsync on a configuration class.
Page 16 | coderblueprint
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
bullet
Return types: void (fire-and-forget), or Future<T>/CompletableFuture<T> if the caller needs the
eventual result.
bullet
Always configure a custom ThreadPoolTaskExecutor bean - the default SimpleAsyncTaskExecutor
creates a new thread per call with no pooling/limits, which can exhaust resources under load.
bullet
Exceptions thrown inside a void @Async method are swallowed unless you configure an
AsyncUncaughtExceptionHandler.
bullet
@Async is proxy-based AOP, so self-invocation (calling the async method from within the same class)
does NOT go through the proxy and runs synchronously.
@Async
public CompletableFuture<String> processOrder(Order order) {
// long-running work
return [Link]("done");
}
16. ExecutorService - Deep Dive
Q51. What is ExecutorService and why use it over creating raw Threads?
Creating a new Thread per task is expensive and unbounded (can exhaust memory/CPU under load).
ExecutorService, from [Link], manages a pool of reusable worker threads, decoupling task
submission from execution, and provides lifecycle control (shutdown, shutdownNow, awaitTermination) and
result handling via Future.
Q52. What are the different types of thread pools in Executors?
bullet
newFixedThreadPool(n) - fixed number of threads; extra tasks wait in an unbounded queue; good for a
known, stable workload.
bullet
newCachedThreadPool() - creates new threads as needed and reuses idle ones (idle threads killed
after 60s); good for many short-lived async tasks but risky under heavy load (unbounded thread
creation).
bullet
newSingleThreadExecutor() - a single worker thread, tasks execute sequentially in submission order.
bullet
newScheduledThreadPool(n) - supports delayed and periodic task execution (scheduleAtFixedRate,
scheduleWithFixedDelay).
bullet
In production, it's now recommended to build a ThreadPoolExecutor explicitly (core size, max size,
queue capacity, RejectedExecutionHandler) rather than the Executors factory methods, since some
factory methods use unbounded queues that can cause OutOfMemoryError.
Q53. Explain the core parameters of ThreadPoolExecutor.
bullet
corePoolSize - minimum number of threads kept alive even when idle.
bullet
maximumPoolSize - max threads allowed when the queue is full.
bullet
keepAliveTime - how long idle threads beyond corePoolSize wait before terminating.
bullet
workQueue - holds tasks waiting for a free thread (e.g. LinkedBlockingQueue, ArrayBlockingQueue,
SynchronousQueue).
bullet
RejectedExecutionHandler - strategy when both the pool and queue are full: AbortPolicy (throws
exception, default), CallerRunsPolicy (caller thread runs the task, provides natural backpressure),
DiscardPolicy, DiscardOldestPolicy.
Q54. Difference between Future and CompletableFuture?
Page 17 | coderblueprint
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
Future represents the result of an asynchronous computation but only supports a blocking get() to retrieve
the result - it has no way to attach a callback, combine with other futures, or handle exceptions declaratively.
CompletableFuture (Java 8+) implements Future but adds a rich, non-blocking, functional API:
thenApply/thenAccept for transforming results, thenCompose for chaining dependent async calls,
thenCombine for combining two independent futures, and exceptionally/handle for error handling - enabling
full async pipelines without blocking any thread.
Q55. How do you properly shut down an ExecutorService?
[Link](); // stop accepting new tasks, let existing ones finish
try {
if () {
[Link](); // force-cancel remaining tasks
}
} catch (InterruptedException e) {
[Link]();
[Link]().interrupt();
}
17. Microservices - Types, Communication, Circuit
Breaker & JWT
Q56. What are Microservices and how are they different from Monolithic architecture?
A microservices architecture splits an application into small, independently deployable services, each owning
its own data store and business capability, communicating over the network (typically HTTP/REST or
messaging). A monolith, in contrast, is a single deployable unit with a shared codebase and database.
Microservices give independent scaling, technology flexibility, and fault isolation, but add complexity around
network calls, data consistency, and operational overhead (deployment, monitoring, tracing).
Q57. How do microservices communicate with each other?
bullet
Synchronous - REST over HTTP (simplest, but couples availability - if the callee is down, the call fails),
or gRPC (binary, faster, uses Protocol Buffers, supports streaming).
bullet
Asynchronous - message brokers like Kafka or RabbitMQ, where a service publishes an event and one
or more services consume it independently; this decouples services in time and improves resilience.
bullet
Service discovery (Eureka, Consul) lets services find each other's network location dynamically instead
of hardcoding hostnames.
bullet
An API Gateway (Spring Cloud Gateway, Netflix Zuul, Kong) sits at the edge, routing external client
requests to the right internal service, and can also handle auth, rate limiting, and request aggregation.
Q58. What is the Circuit Breaker pattern and how is it implemented (Resilience4j)?
Circuit Breaker prevents a service from repeatedly calling a downstream dependency that is already failing,
avoiding cascading failures and wasted resources/threads. It has three states:
bullet
CLOSED - requests flow normally; failures are counted.
bullet
OPEN - once the failure rate crosses a threshold, the circuit 'trips' and calls fail immediately (fast-fail)
without hitting the downstream service, for a configured wait duration.
bullet
HALF_OPEN - after the wait duration, a limited number of trial requests are allowed through; if they
succeed, the circuit closes again, otherwise it re-opens.
Page 18 | coderblueprint
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
@CircuitBreaker(name = "inventoryService", fallbackMethod = "fallback")
public String checkInventory(String sku) {
return [Link]("[Link] + sku, [Link]);
}
public String fallback(String sku, Throwable t) {
return "Inventory service unavailable, please try later";
}
Q59. What is JWT and how is it used for authentication in microservices?
JWT (JSON Web Token) is a compact, self-contained, digitally signed token with three Base64-encoded
parts: Header (algorithm), Payload (claims - user id, roles, expiry), and Signature (verifies the token hasn't
been tampered with, using HMAC or RSA).
bullet
Flow: user logs in -> Auth service validates credentials and issues a JWT -> client sends the JWT in the
Authorization: Bearer <token> header on every subsequent request -> each microservice
independently validates the signature and reads claims, without calling back to the Auth service or a
shared session store.
bullet
This makes JWT ideal for stateless microservices - no server-side session storage is needed, and any
service that trusts the signing key can validate the token.
bullet
Access tokens are short-lived; a longer-lived Refresh token is used to obtain a new access token
without re-authenticating.
bullet
Care needed: tokens can't be easily revoked before expiry (mitigated with short expiry + a token
blacklist/Redis check, or opaque tokens validated against an Auth server).
Q60. What are the different types/patterns of microservices decomposition?
bullet
Decomposition by Business Capability - each service maps to a business function (Order Service,
Payment Service, Inventory Service).
bullet
Decomposition by Subdomain (DDD) - services align with Domain-Driven Design bounded contexts.
bullet
Strangler Fig pattern - incrementally migrating a monolith to microservices by routing specific
functionality to new services while the rest still hits the monolith.
bullet
Saga pattern - manages distributed transactions across services using a sequence of local transactions
with compensating actions on failure (choreography-based via events, or orchestration-based via a
central coordinator).
bullet
API Composition / CQRS - for queries that need data from multiple services, either aggregate at the
gateway/API composer, or maintain a separate read-optimized view updated via events (CQRS).
Q61. How is Distributed Tracing / Observability handled in microservices?
Since a single user request can span many services, tools like Spring Cloud Sleuth (or Micrometer Tracing in
newer Spring Boot) attach a unique Trace ID and Span ID to each request, propagated across service
boundaries via HTTP headers. These traces are collected and visualized in tools like Zipkin or Jaeger,
alongside centralized logging (ELK stack) and metrics (Prometheus + Grafana) for full observability.
18. Spring Security
Q62. Explain the Spring Security filter chain and authentication flow.
Every incoming HTTP request passes through a chain of Servlet Filters before reaching the
DispatcherServlet. Key filters include UsernamePasswordAuthenticationFilter (form login),
Page 19 | coderblueprint
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
BasicAuthenticationFilter, and a custom JwtAuthenticationFilter for token-based auth. The
AuthenticationManager delegates to one or more AuthenticationProvider implementations to actually verify
credentials (e.g. checking a hashed password via a UserDetailsService), and on success populates the
SecurityContext with an Authentication object that the rest of the request can rely on.
Q63. How do you secure a REST API with JWT in Spring Security?
Since REST APIs are stateless, session-based login (JSESSIONID cookies) is replaced with a custom filter
that extracts the JWT from the Authorization header, validates its signature/expiry, loads the user's
authorities from the token claims, and manually sets the Authentication into the SecurityContextHolder - all
before the request reaches the controller. Session creation is disabled with
[Link].
[Link](csrf -> [Link]())
.sessionManagement(sm -> [Link]([Link]))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/auth/**").permitAll()
.anyRequest().authenticated())
.addFilterBefore(jwtAuthFilter, [Link]);
Q64. Difference between Authentication and Authorization?
Authentication answers 'who are you?' - verifying identity (username/password, JWT, OAuth token).
Authorization answers 'what are you allowed to do?' - checking whether the authenticated user has
permission for a specific action or resource, typically via roles/authorities
(@PreAuthorize("hasRole('ADMIN')")).
Q65. What is CSRF and why is it usually disabled for stateless REST APIs?
CSRF (Cross-Site Request Forgery) tricks an authenticated user's browser into submitting an unwanted
request using their existing session cookie. Spring Security's CSRF protection is relevant for
cookie/session-based browser apps. For stateless REST APIs authenticated via a bearer token in a header
(not an automatically-sent cookie), CSRF isn't applicable in the same way since the token must be explicitly
attached by the client, so it's commonly disabled - though care is still needed if tokens are ever stored in
cookies.
19. AWS Services (commonly asked for Java/Spring
Boot roles)
Q66. Which AWS services are commonly asked about for a Java/Spring Boot backend
role?
bullet
EC2 - virtual servers to host the application; key concepts: AMIs, instance types, Auto Scaling Groups,
Security Groups (instance-level firewall).
bullet
S3 - object storage for files/static assets/backups; durability via versioning, lifecycle policies to move
data to Glacier for cost savings.
bullet
RDS - managed relational databases (MySQL/Postgres/Oracle); handles backups, patching, Multi-AZ
failover, read replicas for scaling reads.
bullet
Elastic Load Balancer (ALB/NLB) - distributes incoming traffic across multiple EC2 instances/containers
for high availability.
Page 20 | coderblueprint
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
bullet
Lambda - serverless functions that run code in response to events (API Gateway request, S3 upload,
SQS message) without managing servers, billed per invocation/duration.
bullet
SQS - managed message queue for decoupling services asynchronously (standard =
at-least-once/best-effort ordering, FIFO = exactly-once processing and strict ordering).
bullet
SNS - pub/sub notification service, often paired with SQS (fan-out pattern: one SNS topic delivering to
multiple SQS queues).
bullet
IAM - manages users, roles, and fine-grained permissions/policies for who can access which AWS
resource.
bullet
CloudWatch - metrics, logs, and alarms for monitoring application and infrastructure health.
bullet
ECS / EKS - container orchestration for running Dockerized Spring Boot apps (ECS is AWS-native;
EKS is managed Kubernetes).
bullet
API Gateway - manages, secures, and throttles API endpoints, often fronting Lambda functions.
Q67. How would you deploy a Spring Boot application on AWS (typical setup)?
A common pattern: package the app as a Docker image, push it to ECR (Elastic Container Registry), deploy
it on ECS Fargate (serverless containers, no EC2 management) or EKS, put it behind an Application Load
Balancer, use RDS for the database, store secrets in AWS Secrets Manager or Parameter Store, and
monitor with CloudWatch. For simpler use cases, Elastic Beanstalk offers a more managed, opinionated
deployment path directly from a JAR file.
20. Apache Kafka - Topics, Producers, Consumer
Groups & Idempotency
Q68. Explain Kafka's core architecture - Topics, Partitions, Brokers.
A Kafka Topic is a named, append-only log of messages, split into one or more Partitions for parallelism and
scalability. Each partition is an ordered, immutable sequence of messages, and order is guaranteed only
within a partition, not across the whole topic. A Broker is a single Kafka server; a cluster consists of multiple
brokers, and each partition is replicated across brokers for fault tolerance (one broker holds the 'leader'
replica that handles all reads/writes, others hold 'follower' replicas that stay in sync).
Q69. How do Kafka Producers and Consumer Groups work?
bullet
A Producer sends messages to a topic; it can specify a key, and Kafka uses the key's hash to
consistently route messages with the same key to the same partition, preserving order for that key (e.g.
all events for the same order ID land on one partition).
bullet
A Consumer Group is a set of consumers that jointly consume a topic - Kafka guarantees each partition
is consumed by only ONE consumer within a group at a time, enabling horizontal scaling (add more
consumers, up to the number of partitions, to increase throughput).
bullet
Multiple consumer groups can independently consume the same topic in full - the
partition-to-single-consumer rule only applies within a group.
bullet
Consumers track their position via an 'offset' per partition, periodically committed back to Kafka (in an
internal __consumer_offsets topic), so a restarted consumer resumes from where it left off.
Q70. What is Kafka Idempotency and how do you avoid duplicate message processing?
Page 21 | coderblueprint
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
bullet
Producer idempotency - enabling [Link]=true assigns each producer a unique Producer
ID and a sequence number per partition, so Kafka brokers can detect and discard duplicate retries of
the same message (e.g. caused by a network timeout after the write actually succeeded), guaranteeing
exactly-once delivery at the producer-to-broker level.
bullet
Consumer-side idempotency - since Kafka's default delivery semantics are 'at-least-once' (a consumer
might reprocess a message after a crash/rebalance before committing its offset), the consuming
application itself must be designed to be idempotent - e.g. using a unique message/business key to
check 'have I already processed this?' before applying it (via a DB unique constraint, a processed-IDs
table, or idempotent upsert operations) so re-delivery doesn't cause duplicate side effects.
bullet
For true exactly-once processing end-to-end, Kafka also supports Transactions ([Link]) so a
consume-process-produce cycle can be committed atomically across topics.
Q71. Difference between Kafka and traditional Message Queues like RabbitMQ?
bullet
Kafka retains messages for a configured retention period (or forever) even after consumption, allowing
multiple independent consumers to replay history; RabbitMQ typically removes a message once
acknowledged/consumed.
bullet
Kafka is built for very high throughput, ordered log-based streaming (event sourcing, log aggregation,
stream processing); RabbitMQ is a more traditional message broker with richer routing (exchanges,
topic/fanout/direct bindings) suited to complex routing logic and lower-latency task queues.
bullet
Kafka scales via partitions and consumer groups; RabbitMQ scales via more queues/consumers and
clustering.
21. General / Frequently Asked Core Java Questions
Q72. What is the difference between == and equals()?
== compares references for objects (checks if both point to the same memory location) or actual values for
primitives. equals() (when properly overridden, e.g. in String, wrapper classes, or your own classes)
compares logical/content equality. Two different String objects with the same characters are '==' false but
'.equals()' true, unless they come from the String pool via literals.
Q73. What is the difference between String, StringBuilder and StringBuffer?
bullet
String - immutable; every modification creates a new object; safe to share across threads but inefficient
for heavy concatenation in a loop.
bullet
StringBuilder - mutable, NOT thread-safe, faster; use for single-threaded string building (e.g. inside a
loop).
bullet
StringBuffer - mutable and thread-safe (synchronized methods), but slower than StringBuilder due to
synchronization overhead; rarely needed today since most string-building happens on a single thread.
Q74. Why is String immutable in Java?
bullet
Security - Strings are used for things like class names, file paths, network connections, and DB URLs;
immutability prevents them from being altered after validation.
bullet
String pool / caching - immutability lets the JVM safely reuse the same String object for identical literals,
saving memory.
bullet
Thread safety - an immutable object can be freely shared across threads without synchronization.
bullet
HashCode caching - since content can't change, String caches its hashCode after first computation,
making it a very efficient HashMap key.
Page 22 | coderblueprint
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
Q75. Difference between abstract class and interface?
bullet
An abstract class can have both abstract and concrete methods, constructors, instance state/fields, and
any access modifier; a class can extend only ONE abstract class.
bullet
An interface (pre-Java 8) could only declare abstract methods and constants; since Java 8 it can also
have default and static methods, and since Java 9, private methods - but still no instance state (only
implicitly public static final fields). A class can implement MULTIPLE interfaces.
bullet
Use an abstract class for a strong 'is-a' relationship with shared code/state; use an interface to define a
contract/capability that unrelated classes can all implement (e.g. Comparable, Serializable).
Q76. Explain method overloading vs overriding.
bullet
Overloading - same method name, different parameter list, within the SAME class; resolved at compile
time (static/early binding).
bullet
Overriding - subclass provides a specific implementation of a method already defined in its superclass,
with the SAME signature; resolved at runtime based on the actual object type (dynamic/late binding),
enabling polymorphism.
Q77. What is the difference between checked and unchecked exceptions?
Checked exceptions (subclasses of Exception, excluding RuntimeException) must be either caught or
declared in the method signature with 'throws' - the compiler enforces handling (e.g. IOException,
SQLException), typically representing recoverable conditions external to the program. Unchecked exceptions
(subclasses of RuntimeException, like NullPointerException, ArrayIndexOutOfBoundsException) are not
required to be declared or caught, and typically represent programming bugs.
Q78. What is the 'volatile' keyword and how is it different from 'synchronized'?
volatile guarantees visibility - any write to a volatile variable by one thread is immediately visible to all other
threads (it prevents CPU/JIT caching of the variable in a thread-local register), but it does NOT provide
atomicity for compound operations (like i++). synchronized provides both visibility AND atomicity/mutual
exclusion by acquiring a lock, ensuring only one thread executes the critical section at a time, but at a higher
performance cost. Use volatile for simple flags (e.g. a boolean 'running' flag checked by multiple threads);
use synchronized (or [Link] classes) when a compound read-modify-write needs to be
atomic.
Q79. What are Java Memory Model guarantees around the 'final' keyword?
A final field, once fully initialized in the constructor, is guaranteed to be visible to all threads that see a
reference to the object, without needing extra synchronization - this is why immutable objects (with all-final
fields) are inherently thread-safe for reads, as long as the object reference itself isn't published unsafely (e.g.
leaking 'this' before construction finishes).
Q80. What is the difference between throw and throws?
throw is used inside a method body to actually raise/instantiate a specific exception at runtime (throw new
IllegalArgumentException("bad input")). throws is used in a method signature to declare that the method
might propagate one or more checked exceptions to its caller, who must then handle or further declare them.
Q81. What is Garbage Collection and how do the common GC algorithms differ?
bullet
Serial GC - single-threaded, stop-the-world; best for small applications/single-CPU environments.
bullet
Parallel GC - multiple threads for young-gen collection, still stop-the-world but faster than Serial;
throughput-oriented (default in older JDKs).
Page 23 | coderblueprint
CODERBLUEPRINT Java / Spring Boot / Microservices Interview Guide
bullet
G1 (Garbage First) GC - divides heap into regions, prioritizes collecting regions with the most garbage
first, aims for predictable pause times; default GC since Java 9.
bullet
ZGC / Shenandoah - modern low-latency collectors designed for sub-millisecond pause times even on
very large (multi-GB/TB) heaps.
Q82. What is the difference between process and thread, and what causes a deadlock?
A process is an independent program with its own memory space; a thread is a lightweight unit of execution
within a process, sharing the same memory/heap with other threads of that process, which is what makes
inter-thread communication fast but also introduces synchronization concerns.
A deadlock occurs when two or more threads are each waiting for a lock held by the other, so neither can
proceed - classic example: Thread A holds Lock1 and waits for Lock2, while Thread B holds Lock2 and waits
for Lock1. Prevention: always acquire multiple locks in a consistent global order, use tryLock() with a timeout,
or minimize the scope/number of locks held simultaneously.
Page 24 | coderblueprint