Prices shown are a USD base. Your local-market price is calculated at checkout in your own currency, plus any local sales tax.
What is inside
20 chapters, in the order the interviews tend to ask them:
Collections, generics and the iterator model
Concurrency, memory model and locking
Virtual threads and the executor model
JVM memory and garbage collection
Records, sealed types and pattern matching
Exceptions and error contract design
Maven, Gradle and reproducible builds
Spring Boot auto-configuration and externalised config
Dependency injection and the bean lifecycle
Spring MVC controllers and the HTTP layer
Spring Data JPA repositories and query derivation
Entity mapping, relationships and schema design
Transactions, propagation and isolation
Spring Security, OAuth2 and API authorisation
Bean validation and API error contracts
Testing Spring applications
Caching and query performance
Logging, metrics and tracing
Asynchronous work and message driven design
Microservices and cloud native deployment
How the answers are built
Each chapter opens with the checklist the question is really testing. A few from this pack:
A HashMap is one array of buckets holding a linked list or a tree per bucket, so get is amortised constant time while iteration order is deliberately unspecified.
Without a happens-before edge the Java Memory Model permits a reader to see a stale field indefinitely, so every safely published value needs a final field, a volatile write or a lock.
A virtual thread is scheduled on a ForkJoinPool carrier and its stack lives on the heap, so one costs a few hundred bytes rather than a megabyte of thread memory.
Objects live on the heap while frames live on the stack, so a StackOverflowError is normally a thread local recursion depth problem rather than a heap sizing problem.
A record generates a final class with accessors named after its components, so equals, hashCode and toString come for free and are correct by default.
FillInStackTrace dominates the cost of building a Throwable, so a validation guard that throws per request is a performance decision rather than a style one.
Questions this pack covers
When would you reach for ArrayList over LinkedList in production code?
How do HashMap and HashSet differ in how they treat null keys and null elements?
What does the Java Memory Model actually guarantee about visibility of writes?
How does a happens-before relationship apply to a final field?
How does the scheduler choose a carrier thread for a virtual thread?
What happens to a virtual thread during a blocking file read?
What are the runtime data areas and what lives in each of them?
Why is a StackOverflowError not necessarily a recursion bug?
Each one is answered in full in the pack, with the reasoning written out rather than a bullet list.