The final 48 hours: rapid-fire revision
A 48-hour, 24-hour and 1-hour plan before a Java interview, 60 tickable rapid-fire questions with crisp Java 21 answers, eight classic what-does-it-print puzzles, the project questions you will get, and how to recover when you blank.
On this page
- Picture it first: the last 48 hours
- Rapid-fire: core Java, OOP and strings
- Rapid-fire: equals, hashCode and exceptions
- Rapid-fire: collections and HashMap
- Rapid-fire: concurrency and the Java memory model
- Rapid-fire: JVM memory and GC
- Rapid-fire: Java 8 to 21 and patterns
- What does it print? Eight classic puzzles
- The questions you'll be asked about your project
- How to recover when you blank
- The day-of checklist
- How to say it in the interview
⏱️ What is this sheet?
It's the last thing you read before a Java interview: a plan for the final 48 hours, a rapid-fire round of 60 questions with the exact answers interviewers expect, eight "what does it print?" puzzles, and a script for the moments you blank. Think of it as a pre-flight checklist: a pilot doesn't relearn how to fly before take-off, they run through the items that cause crashes when missed. Every answer here is correct for Java 21.
For this sheet, we'll switch from learning to recall. In the last two days, re-reading notes feels productive but barely moves your score; answering out loud without looking does. So each item below is a question you answer first, then check, then tick. If you can't answer one cleanly, the link at the top of its section takes you to the Last-Mile sheet that covers it.
Below the line (out of scope)
- New topics. If you haven't met virtual threads or G1 tuning yet, 48 hours out isn't the time; skim the 30-second answer in the matching sheet and move on.
- Full explanations: each section links to its sheet, starting with The can't-skip Java interview checklist.
- The 15 and 30-day plans that lead up to this: How to use Last-Mile Java.
The 30-second answer
Forty-eight hours out, find your gaps: take the can't-skip checklist cold, fix only what you missed, rehearse your project story out loud and do one timed design problem. Twenty-four hours out, run this rapid-fire round and the eight puzzles, stop learning new material, sort out logistics, and sleep. In the last hour, read only your own one-page summary, warm up by saying two answers out loud and writing one small piece of code by hand, then go in. In the room, answer in three beats (the fact, the why, one example or number), think out loud when you're stuck, and never bluff: "I'm not sure, here's how I'd reason about it" scores better than a confident wrong answer.
What you’ll learn
- Follow a concrete 48h, 24h and 1h plan that turns revision into recall instead of re-reading
- Answer 60 rapid-fire questions across core Java, strings, exceptions, collections, concurrency, the JVM, Java 8 to 21 and patterns in one to three sentences
- Predict the output of the eight classic puzzles: Integer cache, String ==, finally return, init order, null overloading, mutable keys, for-each remove and volatile count++
- Prepare a two-minute project story and the follow-ups interviewers ask about your own system
- Use a recovery script when you blank, and run the day-of checklist
Interview radar
Asked very often: The quick-fire opener: == vs equals, HashMap internals, checked vs unchecked, volatile, final vs finally vs finalize, what's new in Java 21.
Senior rounds probe: The follow-up after each quick answer ("why?", "what breaks?", "what would you see in production?"), plus deep questions on your own project.
Production angle: Most "what does it print?" puzzles are real bugs in disguise: a cached Integer compared with ==, a mutated HashSet key, a lost update on a volatile counter.
01Picture it first: the last 48 hours
The shape of the last two days matters more than the hours you put in. Each phase has a different job: the first finds gaps, the second makes recall fast, and the last hour only warms you up. The timeline below shows what goes in each block and, as importantly, what doesn't.
A timeline from 48 hours to the interview: at 48 hours, find gaps with the checklist, rehearse the project story and do one timed design problem; at 24 hours, run the rapid-fire round and puzzles, stop new topics, fix logistics and sleep 7 to 8 hours; at 1 hour, read your one-page summary, warm up out loud and write one snippet by hand; then the interview
48 hours out: find the gaps
- Take the can't-skip checklist cold. No notes. Mark each item green (said it cleanly), amber (got there slowly) or red (couldn't). Spend the rest of the day on red only.
- Rehearse out loud, not in your head. Pick the 10 questions you'd hate to get and answer each in under 90 seconds. Record yourself once; you'll hear the filler words and the missing "why".
- Do one timed design problem. 45 minutes, parking lot or rate limiter, following the LLD Rulebook. Practise naming each pattern and the change it protects against (patterns sheet).
- Write your project story (the section below) on one page, and say it out loud twice.
24 hours out: make recall fast
- Run the rapid-fire round below. Tick only what you answered without peeking. Second pass on the unticked ones only.
- Do the eight puzzles. Predict, then read. These are the questions where a confident wrong answer hurts most.
- Stop new topics by the evening. A half-learned topic the night before tends to come out muddled and knock your confidence on the ones you did know.
- Fix logistics: test the video link, camera, mic and a shared editor; for on-site, route and ID. Prepare two or three questions to ask them.
- Sleep 7 to 8 hours. Memory consolidation happens during sleep; an all-nighter trades tomorrow's recall for tonight's reading.
1 hour out: warm up, don't cram
- Read only your own one-page summary, or the
BOARDboxes from the Last-Mile sheets. Nothing new. - Say two answers out loud: the HashMap
putpath and your project story's first 30 seconds. Your voice needs a warm-up as much as your memory does. - Write one snippet by hand: a thread-safe singleton or a
ConcurrentHashMap.mergecounter. It wakes up the "typing code while talking" skill. - Join 5 to 10 minutes early, water nearby, notifications off.
02Rapid-fire: core Java, OOP and strings
Answer each out loud first, then check. One to three sentences is the target length in a quick-fire round; the interviewer will ask for more if they want it. Full coverage: Core Java and OOP: the must-knows and String immutability.
- Q: Is Java pass-by-value or pass-by-reference? A: Always pass-by-value. For an object, the value copied is the reference, so the method can mutate the object but reassigning the parameter never affects the caller's variable.
- Q: JDK vs JRE vs JVM? A: The JVM runs bytecode; the JRE is the JVM plus the class libraries; the JDK adds tools like
javac,jar,jlinkandjcmd. Since Java 11, Oracle no longer ships a separate JRE; you usejlinkto build a trimmed runtime. - Q: Overloading vs overriding? A: Overloading picks a method at compile time from the static argument types; overriding picks at run time from the receiver's actual class. Static and private methods aren't overridden; a static method with the same signature in a subclass hides the parent's.
- Q: Abstract class vs interface in Java 21? A: An interface can have
default,staticandprivate(Java 9+) methods but no instance fields; a class can implement many interfaces. An abstract class can hold state and constructors, but you can extend only one. - Q: What does
finalmean on a class, a method and a variable? A: No subclasses, no overriding, and assign-once respectively. Afinalreference can't be reassigned, but the object it points to can still be mutated. - Q:
final,finally,finalize? A: A modifier, a block that runs aftertry/catch, and anObjectmethod called before GC.finalizehas been deprecated for removal since Java 18 (JEP 421); usetry-with-resources orCleaner. - Q: Static nested class vs inner class? A: An inner class holds a hidden reference to its enclosing instance, so it can keep that instance alive (a classic leak); a static nested class doesn't. Default to static nested.
- Q: How do you make a class immutable? A: Make it
finalwithprivate finalfields, no setters, defensive copies of mutable inputs and outputs, and don't leakthisfrom the constructor. A record covers most of this, but its components are only shallowly immutable. - Q: What does a record generate? A: A
finalclass withprivate finalfields, a canonical constructor, accessors, andequals,hashCodeandtoStringbased on all components (final since Java 16). It can't extend another class but can implement interfaces. - Q: Why is
Stringimmutable? A: So pooled literals can be shared safely, the hash code can be cached, it's thread-safe without locks, and values checked for security (file paths, class names) can't change after the check. - Q: Where is the string pool? A: On the heap since Java 7 (before that, PermGen). Literals and compile-time constants are interned automatically;
intern()adds others. - Q: How many objects does
new String("hi")create? A: Up to two: the"hi"literal in the pool (if it isn't there yet) and a newStringobject on the heap. The copy shares the literal's backing array rather than duplicating the characters. - Q:
StringBuildervsStringBuffer? A: Same API;StringBuffersynchronizes every method,StringBuilderdoesn't. UseStringBuilder; a single builder is almost never shared across threads. - Q: What are compact strings? A: Since Java 9, a
Stringstores Latin-1 text in abyte[]at 1 byte per char, falling back to UTF-16 (2 bytes per char) only when needed, which roughly halves memory for ASCII-heavy data.
03Rapid-fire: equals, hashCode and exceptions
Full coverage: Core Java and OOP: the must-knows, Exceptions: the must-knows and The equals() and hashCode() contracts.
- Q:
==vsequals()? A:==compares references for objects (values for primitives);equalscompares logical value if the class overrides it.Object.equalsis identity. - Q: State the
hashCodecontract. A: Equal objects must return equal hash codes, and the hash must stay stable while the fields used byequalsdon't change. Unequal objects may collide. - Q: What happens if you override
equalsbut nothashCode? A: It compiles and runs, butHashMap.getandHashSet.containsusually miss, because equal keys land in different buckets. You can end up with two "equal" keys in one map. - Q:
ComparablevsComparator? A:Comparable.compareTois the class's single natural order; aComparatoris an external, pluggable order. KeepcompareToconsistent withequals, orTreeSetandHashSetdisagree (new BigDecimal("1.0")and"1.00"are one element in aTreeSet, two in aHashSet). - Q: Checked vs unchecked exceptions? A: Checked exceptions extend
Exceptionbut notRuntimeException, and the compiler forces you to catch or declare them. Unchecked ones areRuntimeExceptionandErrorsubclasses. - Q: Should you catch
Error? A: Generally no:OutOfMemoryErrorandStackOverflowErrormean the JVM is in trouble. Catch them only at a top-level boundary to log and exit cleanly. - Q: Does
finallyalways run? A: It runs on normal completion,return,breakand exceptions. It doesn't run if the JVM stops first:System.exit,Runtime.halt, a crash, a killed process, or a daemon thread still insidetrywhen the JVM exits. - Q: What does try-with-resources guarantee? A: Every
AutoCloseableis closed in reverse order of declaration, even on exception. Ifclose()also throws, that exception is attached as suppressed to the primary one (getSuppressed()) instead of hiding it. - Q: Can an overriding method throw a broader checked exception? A: No. It may throw the same, narrower or no checked exceptions, and any unchecked ones, so callers of the parent type stay correct.
04Rapid-fire: collections and HashMap
Full coverage: Collections and HashMap: the must-knows.
- Q: Walk through
HashMap.put. A: Computeh = key.hashCode(), spread it withh ^ (h >>> 16), pick the bucket with(n - 1) & hash, then walk the bucket comparing stored hash,==andequals; replace the value on a match, otherwise append a node. If the size passes the threshold, resize. - Q: Default capacity, load factor and resize? A: 16 buckets, load factor 0.75, so the first resize happens when the 13th entry goes in (threshold 12). Resizing doubles the table, and each node either stays at index
ior moves toi + oldCapacity. - Q: When does a bucket become a tree? A: When one bucket's chain grows past 8 nodes (
TREEIFY_THRESHOLD = 8) and the table has at least 64 buckets; below 64, the map resizes instead. A resize turns it back into a list at 6 nodes or fewer. A bad bucket then costs O(log n) instead of O(n). - Q: Nulls in
HashMap,HashtableandConcurrentHashMap? A:HashMapallows onenullkey and any number ofnullvalues.HashtableandConcurrentHashMapallow neither, because in a concurrent mapgetreturningnullwould be ambiguous. - Q: How does
ConcurrentHashMapwork in Java 8+? A: No segments: it CASes a node into an empty bin andsynchronized-locks only the bin's head node otherwise, whilegettakes no lock. Usemerge,computeandputIfAbsentfor atomic read-modify-write. - Q: Fail-fast vs weakly consistent iterators? A:
ArrayListandHashMapiterators checkmodCountand throwConcurrentModificationExceptionon a structural change not made through the iterator. Concurrent collections' iterators never throw; they may or may not reflect changes made during iteration. - Q:
ArrayListvsLinkedList? A:ArrayListgives O(1) random access, amortised O(1) append and grows by 1.5x;LinkedListis O(n) to index and cache-unfriendly. Default toArrayList, andArrayDequefor queues and stacks. - Q: How is
HashSetimplemented? A: It wraps aHashMapwhose keys are the set's elements and whose values are one shared dummy object. So the sameequals/hashCoderules apply. - Q:
List.ofvsArrays.asList? A:List.of(Java 9+) is fully unmodifiable and rejectsnullelements with an NPE.Arrays.asListis fixed-size but allowsset, and writes through to the backing array. - Q: How do you build an LRU cache with the JDK? A: Extend
LinkedHashMapwithaccessOrder = truein the constructor and overrideremoveEldestEntryto returnsize() > capacity. Wrap it or lock it for concurrent use.
05Rapid-fire: concurrency and the Java memory model
Full coverage: Multithreading and the JMM: the must-knows and wait, notify and synchronized.
- Q: What does
volatileguarantee? A: Visibility and ordering: a write to a volatile happens-before every later read of it, so the reader also sees everything written before that write. It does not makecount++atomic. - Q: Name four happens-before rules. A: Unlocking a monitor happens-before a later lock of it; a volatile write happens-before later reads;
Thread.start()happens-before the started thread's actions; a thread's actions happen-before another thread returns fromjoin()on it. - Q:
synchronizedvsReentrantLock? A: Both are reentrant and give the same memory guarantees.ReentrantLockaddstryLockwith a timeout, interruptible locking, optional fairness and multipleConditions, at the price of anunlock()you must put infinally. - Q: Rules for
wait()andnotify()? A: Call them while holding the object's monitor, or you getIllegalMonitorStateException.waitreleases the lock; always call it in awhileloop that re-checks the condition, because of spurious wakeups and stolen signals. - Q:
sleepvswait? A:Thread.sleeppauses without releasing any locks;waitreleases the monitor and waits for a notify, interrupt or timeout. - Q: How do you prevent deadlock? A: Deadlock needs mutual exclusion, hold-and-wait, no preemption and a circular wait. Break the circle with a global lock order, or use
tryLockwith a timeout and back off. - Q: How does
ThreadPoolExecutorhandle a new task? A: Below core size it starts a thread; then it queues; if the queue is full it grows to max size; beyond that it calls the rejection handler.Executors.newFixedThreadPooluses an unbounded queue, so a slow consumer can grow it untilOutOfMemoryError. - Q: What are virtual threads? A: Final in Java 21 (JEP 444): threads scheduled by the JVM onto a small pool of carrier threads, cheap enough to create one per task. In Java 21, blocking inside
synchronizedpins the carrier (fixed in JDK 24 by JEP 491), and you should never pool them. - Q:
thenApplyvsthenCompose? A:thenApplymaps the result with a plain function;thenComposeflat-maps a function that itself returns aCompletableFuture, avoiding a nested future. Async variants without an executor run onForkJoinPool.commonPool(). - Q: Why is
ThreadLocalrisky in a thread pool? A: Pool threads live for the app's lifetime, so values stay reachable and leak between requests. Alwaysremove()in afinally.
06Rapid-fire: JVM memory and GC
Full coverage: JVM memory and garbage collection: the must-knows and Java memory management: heap, G1 and the signals that matter.
- Q: Name the JVM memory areas. A: The heap (objects, shared), one stack per thread (frames with locals), Metaspace (class metadata, in native memory since Java 8 replaced PermGen), the code cache for JIT output, plus PC registers and native stacks.
- Q: What's the default GC in Java 21? A: G1, on any machine with at least 2 CPUs and about 2 GB of memory; on smaller machines the JVM picks Serial. G1 aims for a 200 ms pause target by default.
- Q: What is the generational hypothesis? A: Most objects die young, so the heap is split into a young generation (Eden plus survivor spaces) collected often and cheaply, and an old generation collected rarely. Objects that survive enough young collections get promoted.
- Q: What are GC roots? A: References the collector starts from: local variables on thread stacks, static fields of loaded classes, JNI references and active monitors. Anything not reachable from a root is garbage, cycles included.
- Q: When would you pick ZGC? A: When pause times matter more than throughput, for example latency-sensitive services with large heaps. Its pauses are typically under 1 ms regardless of heap size; Java 21 added generational ZGC (
-XX:+UseZGC -XX:+ZGenerational). - Q: Name three kinds of
OutOfMemoryError. A: "Java heap space" (heap full of live objects), "Metaspace" (too many classes, often a class loader leak), and "unable to create native thread" (OS thread limit). With the Parallel collector, "GC overhead limit exceeded" means over 98% of time went to GC while recovering under 2% of the heap. - Q: How does class loading delegate? A: A loader asks its parent first: application, then platform, then bootstrap. That stops your code from replacing
java.lang.String.
07Rapid-fire: Java 8 to 21 and patterns
Full coverage: Java 8 to 21: the must-knows and Design patterns and SOLID: the must-knows.
- Q: Are streams lazy? A: Yes: intermediate operations only build a pipeline, and nothing runs until a terminal operation. A stream can be consumed once; reusing it throws
IllegalStateException. - Q:
mapvsflatMap? A:mapturns each element into one element;flatMapturns each element into a stream and flattens them, for example a list of orders into a stream of all their items. - Q:
orElsevsorElseGet? A:orElse(x)evaluatesxevery time, even when theOptionalhas a value;orElseGet(supplier)calls the supplier only when empty. UseOptionalfor return types, not fields or parameters. - Q: What makes an interface functional? A: Exactly one abstract method (default and static methods don't count).
@FunctionalInterfacemakes the compiler enforce it. - Q: Name the Java 21 features you'd mention. A: Virtual threads (JEP 444), pattern matching for
switch(JEP 441), record patterns (JEP 440) and sequenced collections (JEP 431), all final. Java 21 is an LTS release, after 17, 11 and 8. - Q: What do sealed classes buy you? A: A
permitslist fixes the subclasses (final since Java 17), so aswitchover them can be exhaustive without adefault, and the compiler flags a missing case when you add a subtype. - Q: Best thread-safe singleton? A: An
enumwith one constant: the JVM guarantees one instance and it's safe against reflection and serialization. For lazy creation, the holder idiom; double-checked locking needs avolatilefield. - Q: Decorator vs proxy? A: Both keep the interface. A decorator adds behaviour and is stacked by the client (
BufferedInputStream); a proxy controls access (lazy loading, caching, transactions) and usually hides that it's there. - Q: Strategy vs state? A: Same shape, different driver: the client picks a strategy, while a state object replaces itself as the context moves through its lifecycle.
- Q: DIP vs dependency injection? A: DIP is the principle that high-level code depends on abstractions it owns; DI is the technique of passing dependencies in, usually via the constructor. Spring is a tool that automates DI.
08What does it print? Eight classic puzzles
These are the questions where you get one shot. Read each, say your prediction out loud, then read the answer. Every one of them is a production bug wearing a puzzle costume.
1. The Integer cache
Try it yourself first
Predict all four lines.
Integer a = 127, b = 127;
Integer c = 128, d = 128;
Long e = 127L;
System.out.println(a == b); // ?
System.out.println(c == d); // ?
System.out.println(c.equals(d)); // ?
System.out.println(e.equals(127)); // ?
true, false, true, false. Autoboxing calls Integer.valueOf, which returns cached objects for -128 to 127 (JLS 5.1.7), so a and b are the same object, while each 128 is a new one. The last line is the sneaky one: 127 boxes to an Integer, and Long.equals returns false for anything that isn't a Long. The upper cache bound can be raised with -XX:AutoBoxCacheMax, which is one more reason never to compare wrappers with ==.
2. String ==
Try it yourself first
Which comparisons print true?
String s1 = "java";
String s2 = "ja" + "va";
String s3 = new String("java");
String half = "ja";
String s4 = half + "va";
final String fixed = "ja";
String s5 = fixed + "va";
System.out.println(s1 == s2); // ?
System.out.println(s1 == s3); // ?
System.out.println(s1 == s4); // ?
System.out.println(s1 == s5); // ?
System.out.println(s1 == s4.intern()); // ?
true, false, false, true, true. "ja" + "va" and fixed + "va" are compile-time constant expressions (a final variable with a constant initializer counts), so the compiler folds them into the pooled "java". half + "va" is computed at run time and creates a new object. intern() returns the pooled copy.
3. return inside finally
Try it yourself first
What do a() and b() return?
static int a() {
try { return 1; }
finally { return 2; }
}
static int b() {
int x = 1;
try { return x; }
finally { x = 2; }
}
a() returns 2: a return in finally overrides the try's return, and it would also silently swallow an exception thrown from try. b() returns 1: the return value is evaluated and saved before finally runs, so changing the local afterwards doesn't affect it. Never return from finally.
4. Initialisation order
Try it yourself first
What does new Child(); new Child(); print?
class Parent {
static { System.out.print("1 "); }
{ System.out.print("2 "); }
Parent() { System.out.print("3 "); }
}
class Child extends Parent {
static { System.out.print("4 "); }
{ System.out.print("5 "); }
Child() { System.out.print("6 "); }
}
1 4 2 3 5 6 2 3 5 6. Static initialisers run once, parent first, when the class is initialised. Each new then runs the parent's instance initialisers and constructor, then the child's instance initialisers and constructor (JLS 12.5). The trap is printing 1 4 twice.
5. Overloading with null
Try it yourself first
What does print(null) print? What if you add a third overload, print(Integer i)?
static void print(Object o) { System.out.println("Object"); }
static void print(String s) { System.out.println("String"); }
print(null);
String. null fits both, and the compiler picks the most specific method: String is a subtype of Object (JLS 15.12.2.5). Add print(Integer) and it doesn't compile: "reference to print is ambiguous", because neither String nor Integer is more specific than the other. Overload resolution happens at compile time, so this is never a runtime error.
6. A mutable key in a HashSet
Try it yourself first
Point has correct equals and hashCode over x and y. Predict the three lines.
class Point {
int x, y;
Point(int x, int y) { this.x = x; this.y = y; }
@Override public boolean equals(Object o) {
return o instanceof Point p && p.x == x && p.y == y;
}
@Override public int hashCode() { return 31 * x + y; }
}
Set<Point> set = new HashSet<>();
Point p = new Point(1, 2);
set.add(p);
p.x = 5;
System.out.println(set.contains(p)); // ?
System.out.println(set.contains(new Point(1, 2))); // ?
System.out.println(set.size()); // ?
false, false, 1. The entry sits in the bucket for hash (1, 2). Looking up p now searches the bucket for (5, 2) and misses; looking up a fresh (1, 2) finds the right bucket, but equals fails against the mutated object. The element is stranded: you can't find it and you can't remove it. Keys must be immutable, which is why records and String make good keys.
7. Removing inside a for-each
Try it yourself first
What happens? Then: what if the condition removes "bob" instead?
List<String> names = new ArrayList<>(List.of("ann", "bob", "cid"));
for (String n : names) {
if (n.equals("ann")) names.remove(n);
}
System.out.println(names);
It throws ConcurrentModificationException. The for-each uses an iterator, names.remove bumps modCount, and the iterator's next next() call notices. The twist: removing "bob", the second-to-last element, doesn't throw. After the removal the size is 2 and the iterator's cursor is 2, so hasNext() returns false, the loop ends, and "cid" is never visited. Use names.removeIf(n -> n.equals("ann")) or Iterator.remove().
8. volatile count++
Try it yourself first
Two threads, 100,000 increments each. What prints?
static volatile int count = 0;
public static void main(String[] args) throws InterruptedException {
Runnable inc = () -> { for (int i = 0; i < 100_000; i++) count++; };
Thread t1 = new Thread(inc), t2 = new Thread(inc);
t1.start(); t2.start();
t1.join(); t2.join();
System.out.println(count);
}
Some number up to 200,000, and on a multi-core machine usually less, different on each run. count++ is three steps (read, add, write), and volatile makes each step visible but doesn't make the three atomic, so two threads read the same value and one update is lost. Fix it with AtomicInteger.incrementAndGet(), LongAdder under heavy contention, or a lock.
09The questions you'll be asked about your project
In most Java rounds, 10 to 20 minutes go to your own work, and it's the part candidates prepare least. The interviewer is checking that you owned something, understood why it was built that way, and can talk about numbers and trade-offs. Prepare a two-minute story with this shape: context and scale, your role, the architecture in one sentence, the hardest problem and how you solved it, the measurable result, and what you'd change.
- Walk me through a project you're proud of. Two minutes, the shape above. End on a number: latency, throughput, cost, incidents.
- What was your exact role? Say "I", not "we", for what you did. Interviewers discount answers that never separate the two.
- Why did you choose X over Y? Have one real trade-off ready for your database, your messaging choice and your framework. "It was already there" is honest; add what you'd pick today and why.
- What was the hardest bug? A concrete production issue: symptom, how you found it (logs, heap dump, thread dump, flame graph), root cause, fix, and what you changed so it couldn't recur.
- How does it handle failure? Timeouts, retries with backoff, idempotency, what happens when a dependency is down.
- How would it handle 10x traffic? Where does it break first: database connections, a lock, a single-threaded consumer, GC pauses? Name the bottleneck before the fix.
- Where did you use concurrency? Thread pools and their sizes, what's shared, how it's protected. Expect a follow-up on
ConcurrentHashMaporCompletableFutureif you mention them. - What would you do differently? One real regret plus what you learned. "Nothing" reads as lack of reflection.
Anything you mention is fair game for a deep follow-up. If you say "we used Kafka", expect "how did you handle duplicate messages?" Only name technologies you can go two questions deep on, and prepare those two questions.
10How to recover when you blank
Blanking happens to strong candidates too, usually on something they know well. What interviewers score is what you do next. Silence for 20 seconds feels like a minute to both of you; a calm, out-loud recovery reads as composure.
- Buy a few seconds honestly. "Let me think about that for a moment." Then actually think, out loud if you can.
- Restate the question. "So you're asking what happens when two threads put the same key at once?" It often unlocks the answer, and it catches misunderstandings.
- Reason from what you're sure of. "I know
HashMapisn't thread-safe and thatputcan trigger a resize, so the risk is..." First-principles reasoning is a strong signal even when you don't land the exact fact. - Bound your answer. "I don't remember the exact threshold; I believe it's 8 nodes per bucket, and here's why a threshold exists at all." A hedged, mostly right answer beats a confident wrong one.
- Ask for a nudge, or park it. "Could you give me a hint on which part you mean?" or "Can I come back to this?" Interviewers want to see you work; most will help.
- Never bluff. An invented API or a made-up number costs more than "I don't know", because it makes the interviewer doubt everything else you said.
Many candidates, after one weak answer, rush the next three to "make up for it" and lose more points than the original miss cost. Each question is scored mostly on its own. Take a breath, reset, and treat the next one as a fresh start.
11The day-of checklist
Tick these on the morning of the interview. None of them is about Java, and every one of them has cost someone a round.
- Setup tested: video link opens, camera and mic work, screen sharing is allowed, laptop charged and plugged in, a backup (phone hotspot) ready.
- Coding environment ready: you know whether it's a shared editor, an IDE or a whiteboard, and you've typed a small class in it once. No autocomplete means you should know
Map.Entry,Collectors.groupingByandExecutorServicesignatures cold. - Your one-pager open for the last hour, and closed when the interview starts.
- Project story said out loud once today, ending on a number.
- Two or three questions for them written down: how the team handles on-call, what a first project looks like, how design decisions get made.
- Water, notifications off, door closed, and 5 to 10 minutes of buffer before the start.
- One reminder to yourself: think out loud, answer in three beats, and say "I'm not sure" rather than bluff.
12How to say it in the interview
When I run a quick-fire round, I'm listening for answers that come in three beats: the fact, the reason, and one example or number. "volatile gives visibility, not atomicity" is the fact; "because count++ is a read, an add and a write" is the reason; "so I'd use an AtomicInteger or LongAdder" is the example. Candidates who stop at the fact sound memorised; candidates who start with the example sound unsure. Three beats, then stop and let me follow up.
In the interview
"Good question. Short version: HashMap isn't thread-safe, so two threads putting at once can lose an update, and before Java 8 a concurrent resize could even create a cycle that hung get. The reason is that put reads and writes the bucket array without any lock or happens-before edge. In production I'd use a ConcurrentHashMap, and if I'm doing read-modify-write like counting, I'd use merge or compute so the update is atomic per key. Want me to go into how ConcurrentHashMap locks per bin?"
Here's what your one-page summary for the last hour might look like:
On the whiteboard
Final 48 hours
- 48h: checklist cold → fix red only · 10 answers out loud · 1 timed LLD · project story
- 24h: rapid-fire + 8 puzzles · no new topics · logistics · sleep 7 to 8h
- 1h: own summary only · say 2 answers · write 1 snippet · join early
- Answer = fact → why → example/number, then stop
- Puzzles: Integer cache -128..127 · constant folding · finally return wins · static once, parent first · null → most specific · mutable key stranded · CME (except 2nd-to-last) · volatile ≠ atomic
- Blank: restate → reason from basics → bound it → ask/park → never bluff
Interview questions for this topicComing soon
Further reading (8)
- JLS 21, 5.1.7: Boxing Conversion (the -128 to 127 cache)
- JLS 21, 15.29: Constant Expressions
- JLS 21, 14.20.2: Execution of try-finally and try-catch-finally
- JLS 21, 12.5: Creation of New Class Instances
- JLS 21, 15.12.2.5: Choosing the Most Specific Method
- JLS 21, Chapter 17.4: Memory Model
- HashMap (Java SE 21 API)
- JEP 444: Virtual Threads