Knowledge Base
A curated collection of interview topics and deep-dives from a comprehensive Gemini-guided preparation session. Covers Spring Boot, Java internals, System Design, and competitive coding patterns.
Think of ordering a burger in a high-end restaurant — the container (Spring IoC) handles everything from instantiation to cleanup, just like the kitchen manages your order from raw ingredients to serving and clearing.
@Component
public class OrderService {
private final PaymentGateway paymentGateway;
// Constructor Injection (recommended)
public OrderService(PaymentGateway paymentGateway) {
this.paymentGateway = paymentGateway;
}
@PostConstruct
public void init() {
// Dependencies are fully injected here
log.info("OrderService initialized with {}", paymentGateway);
}
@PreDestroy
public void cleanup() {
log.info("OrderService shutting down...");
}
}Interview Tip
Interviewers love asking 'Why not just put init logic in the constructor?' — because with field injection, dependencies aren't available yet in the constructor. @PostConstruct guarantees everything is wired.
The "Locked Box" problem: Bean A needs Bean B to be created, and Bean B needs Bean A — a classic deadlock.
Interview Tip
The best answer is always 'refactor the architecture.' Mention @Lazy as a quick fix but emphasize it's a code smell.
The "ATM Withdrawal" — either the money comes out AND your balance updates, or neither happens. All or nothing.
@Service
public class BankService {
@Transactional(rollbackFor = Exception.class)
public void transfer(Account from, Account to, BigDecimal amount) {
from.debit(amount); // Step 1
to.credit(amount); // Step 2
// If Step 2 fails → Step 1 is rolled back automatically
}
// ⚠️ SELF-INVOCATION TRAP
public void processPayroll(List<Employee> employees) {
for (Employee emp : employees) {
this.transfer(company, emp, emp.getSalary());
// ❌ 'this' bypasses the proxy → NO transaction!
}
}
}Interview Tip
Self-invocation is the #1 @Transactional interview trap. The fix? Inject the service into itself, or move the method to another service.
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFound(
ResourceNotFoundException ex, HttpServletRequest request) {
ErrorResponse error = new ErrorResponse(
LocalDateTime.now(),
HttpStatus.NOT_FOUND.value(),
ex.getMessage(),
request.getRequestURI()
);
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidation(
MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getFieldErrors()
.forEach(e -> errors.put(e.getField(), e.getDefaultMessage()));
// Return 400 with field-level error details
return ResponseEntity.badRequest().body(
new ErrorResponse(errors)
);
}
}Interview Tip
The Singleton-in-Prototype trap is a common gotcha. If asked 'What happens when you inject Prototype into Singleton?', the answer is: you get one fixed instance, not a new one each time.
A "Taxi Fleet" — instead of hiring a new driver for every passenger (creating a thread per task), you maintain a fleet and assign available taxis.
ExecutorService pool = Executors.newFixedThreadPool(10);
// Submit tasks
Future<String> future = pool.submit(() -> {
Thread.sleep(1000);
return "Task completed!";
});
// Get result (blocks until ready)
String result = future.get();
pool.shutdown();A "Restaurant Buzzer" — place your order (submit task), get a buzzer, go sit down. The buzzer rings when food is ready.
CompletableFuture<Double> priceFuture =
CompletableFuture.supplyAsync(() -> fetchPrice("AAPL"))
.thenApply(price -> price * 1.1) // Add 10% markup
.thenCombine(
CompletableFuture.supplyAsync(() -> fetchExchangeRate("USD")),
(price, rate) -> price * rate // Convert currency
)
.exceptionally(ex -> {
log.error("Failed", ex);
return 0.0;
});Interview Tip
Explain thenApply vs thenCompose as map vs flatMap — interviewers love the functional programming parallel.
Moving from a fleet of expensive taxis (platform threads) to millions of lightweight drones — each "drone" handles one request but costs almost nothing.
// Java 21 — create virtual threads directly
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 100_000).forEach(i ->
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1));
return i;
})
);
} // Automatically shuts downInterview Tip
Virtual Threads are the hottest Java 21 topic. Key point: they're NOT faster for CPU work — they shine for high-concurrency I/O workloads where threads spend most time waiting.
// Record — replaces entire POJO with getters, equals, hashCode, toString
public record UserDTO(String name, String email, int age) {}
// Sealed interface
public sealed interface Shape permits Circle, Rectangle {
double area();
}
// Pattern matching
if (shape instanceof Circle c) {
System.out.println("Radius: " + c.radius());
}
// Text block
String json = """
{
"name": "Suraj",
"role": "SDE-2"
}
""";Interview Tip
When asked 'What Java version are you on?', always mention the migration path. E.g., 'We migrated from 11 to 17 for Records and sealed classes, and are evaluating 21 for virtual threads.'
Interview Tip
Key insight: Kafka guarantees ordering WITHIN a partition, not across partitions. Use a consistent partition key (e.g., user_id) to ensure all events for one user go to the same partition.
@CircuitBreaker(name = "paymentService", fallbackMethod = "paymentFallback")
@Retry(name = "paymentService", fallbackMethod = "paymentFallback")
public PaymentResponse processPayment(PaymentRequest request) {
return paymentClient.charge(request);
}
public PaymentResponse paymentFallback(PaymentRequest request, Throwable t) {
log.warn("Payment service unavailable, returning cached response", t);
return PaymentResponse.pending(request.getOrderId());
}Interview Tip
Know the three anomalies: Dirty Read (reading uncommitted data), Non-Repeatable Read (row changes between two reads), Phantom Read (new rows appear between two identical queries).
// ❌ VULNERABLE — string concatenation
String sql = "SELECT * FROM users WHERE name = '" + userInput + "'";
// ✅ SAFE — PreparedStatement
String sql = "SELECT * FROM users WHERE name = ?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, userInput);
ResultSet rs = stmt.executeQuery();
// ✅ SAFE — JPA
@Query("SELECT u FROM User u WHERE u.name = :name")
List<User> findByName(@Param("name") String name);Asking 100 questions one-by-one instead of asking all 100 in one meeting. You query the parent (1 query) then lazily load each child (N queries).
Interview Tip
Always mention the performance impact: a page listing 100 orders with items could fire 101 database queries without optimization. JOIN FETCH reduces it to 1.
Interview Tip
The 'treeification threshold of 8' is a classic deep-dive question. Explain that it's a space-time trade-off: tree nodes are bigger, so only worth it when the chain is long enough.
// LC 121 — Single Transaction
public int maxProfit(int[] prices) {
int minPrice = Integer.MAX_VALUE;
int maxProfit = 0;
for (int price : prices) {
minPrice = Math.min(minPrice, price);
maxProfit = Math.max(maxProfit, price - minPrice);
}
return maxProfit;
}
// LC 122 — Multiple Transactions
public int maxProfit2(int[] prices) {
int profit = 0;
for (int i = 1; i < prices.length; i++) {
if (prices[i] > prices[i - 1]) {
profit += prices[i] - prices[i - 1];
}
}
return profit;
}private final String[] ones = {"", "One", "Two", "Three", "Four",
"Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven",
"Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen",
"Seventeen", "Eighteen", "Nineteen"};
private final String[] tens = {"", "", "Twenty", "Thirty", "Forty",
"Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
private final String[] thousands = {"", "Thousand", "Million", "Billion"};
public String numberToWords(int num) {
if (num == 0) return "Zero";
StringBuilder sb = new StringBuilder();
int i = 0;
while (num > 0) {
if (num % 1000 != 0) {
sb.insert(0, helper(num % 1000) + thousands[i] + " ");
}
num /= 1000;
i++;
}
return sb.toString().trim();
}The "Ripple Effect" — drop a stone in water and watch the ripple expand outward. BFS explores all neighbors level by level.
public int numIslands(char[][] grid) {
int count = 0;
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if (grid[i][j] == '1') {
count++;
bfs(grid, i, j);
}
}
}
return count;
}
private void bfs(char[][] grid, int r, int c) {
Queue<int[]> queue = new LinkedList<>();
queue.offer(new int[]{r, c});
grid[r][c] = '0';
int[][] dirs = {{0,1},{0,-1},{1,0},{-1,0}};
while (!queue.isEmpty()) {
int[] cell = queue.poll();
for (int[] d : dirs) {
int nr = cell[0] + d[0], nc = cell[1] + d[1];
if (nr >= 0 && nr < grid.length && nc >= 0 &&
nc < grid[0].length && grid[nr][nc] == '1') {
grid[nr][nc] = '0';
queue.offer(new int[]{nr, nc});
}
}
}
}class EvenOddPrinter {
private int n;
private volatile boolean isOddTurn = true;
public synchronized void printOdd() {
for (int i = 1; i <= n; i += 2) {
while (!isOddTurn) { // while, NOT if
try { wait(); } catch (InterruptedException e) {}
}
System.out.println(Thread.currentThread().getName() + ": " + i);
isOddTurn = false;
notify();
}
}
public synchronized void printEven() {
for (int i = 2; i <= n; i += 2) {
while (isOddTurn) {
try { wait(); } catch (InterruptedException e) {}
}
System.out.println(Thread.currentThread().getName() + ": " + i);
isOddTurn = true;
notify();
}
}
}Interview Tip
Always use while(!condition) instead of if(!condition) before wait(). Spurious wakeups are real — the JVM spec allows threads to wake without being notified.
// Java 21: High-performance parallel log analysis
public Map<String, Long> countErrorsByType(Path logsDir) throws IOException {
try (Stream<Path> paths = Files.walk(logsDir)) {
return paths
.filter(p -> p.toString().endsWith(".log"))
.parallel()
.flatMap(p -> {
try { return Files.lines(p); }
catch (IOException e) { return Stream.empty(); }
})
.filter(line -> line.contains("ERROR"))
.collect(Collectors.groupingBy(
line -> line.split("]")[0].replace("[", "").trim(),
Collectors.counting()
));
}
}Curated from a Gemini conversation — structured and formatted for quick reference.