Java interview prep cheat sheet

javaspringinterview

I asked ChatGPT to interview me based on a job description for a Java/Spring developer position. There were no years of experience required for the job, so I was assuming mid level, but asked for mid/senior level questions.

I don't necessarily think these were senior level questions, but the LLM did a good job regardless.

It's extremely helpful to prepare like this!

I get to answer questions, and the LLM points out the stuff I omitted.

ChatGPT (GPT-5.2) prepared a list of topics to discuss based on its understanding of a mid/senior level Java/Spring interview, and asked me questions about them.

I list the answers here for future reference. Here's to hoping this will be useful to you/me in the future.


  1. Java Core & OOP
  2. Concurrency (Threading & Multiprocessing)
  3. Design Patterns
  4. Spring & Spring Boot
  5. Persistence & Databases (SQL/NoSQL, ORM)
  6. Messaging & Distributed Systems
  7. Testing
  8. Build Tools & DevOps
  9. System Design / Senior-level discussion

1. Java Core & OOP

  1. Differences between == and .equals()? How does it apply to a String? What role does hashCode() play?
  • == compares references (memory addresses for objects)
  • .equals() compares logical equality (object state), depending on implementation
  • String.equals() compares character sequences
  • Equal objects must have the same hashCode()
  • Hash collisions are possible
  • .equals() is defined in Object and should be overridden
  • If .equals() is not overridden, it behaves like ==
  • hashCode() is critical for hash-based collections (HashMap, HashSet)

  1. What happens if you override .equals() but do not override hashCode(), and then use the object as a key in a HashMap?
  • Two objects that are logically equal (equals() == true) will:
  • Produce different hash codes
  • Go into different buckets in a HashMap
  • You cannot retrieve the value using an equal (but different) key object

HashMap lookup steps:

  • Compute hashCode()
  • Find bucket
  • Use equals() to find exact key

3.Why is String immutable?

  • thread safety
  • safe memory optimization (String Pool/String interning)
  • cached hashCode() (computed once, reused), faster lookups in hash-based collections
  • boxed classes are also immutable (Integer, Double, Long, etc.)
  • some degree of TOCTOU (Time of Check, Time of Use) safety
checkPermission(path);
// compromised Java code can not modify 'path' without its reference changing 
openFile(path);

  1. Difference between String, StringBuilder, StringBuffer
  • String - immutable
  • StringBuilder - mutable, not thread-safe
  • StringBuffer - mutable, thread-safe, mostly legacy

  1. Memory & JVM

Stack vs Heap, where are

  • objects
  • local variables
  • static variables
  • String literals

stored?

  • Objects - heap
  • Local variables, object references - stack
  • Static variables - heap
  • String literals - heap (String pool)

2. Concurrency

  1. synchronized vs volatile vs AtomicInteger
  • synchronized:
    • methods or blocks
    • mutual exclusion, critical sections
    • visibility
    • uses locks, OS support for putting threads to sleep (after exhausing CAS period)
    • e.g. more code that needs to be protected
  • volatile
    • visibility, threads always read the latest value
    • not good for ++/-- compound operations
    • e.g. flags
  • AtomicInteger
    • atomic read-modify-write operations
    • lock-free, not synchronized, uses compare-and-swap (CAS) CPU instruction
    • e.g. counters

  1. Difference between wait(), notify(), sleep()
  • wait, notify:
    • live on Object
    • used for condition-based thread coordination
    • must be called from synchronized context (needs a lock)
    • called in a loop with a condition check to avoid bugs, spurious wakeups
    • wait() releases the lock, acquires it when notified, when it returns it already has the lock
    • notify() wakes up a waiting thread
    • notifyAll() wakes up all waiting threads
  • sleep:
    • static on Thread
    • used for thread sleep
    • does not release the lock

  1. Thread pools (ExecutorService) vs manual Threads
  • creating threads manually:
    • expensive (OS resources, stack allocation)
    • too many threads cause context switching, memory pressure, reduced throughput
    • must finish execution before GC'd (garbage collected)
  • using a thread pool (ExecutorService):
    • reuse threads
    • bound concurrency (max thread count)
    • task queueing when all busy
    • separates task submission from execution
    • can be tuned for IO/CPU-bound workloads, foundation for async, reactive

  1. Runnable vs Callable
  • Runnable:
    • no return value
    • no checked exceptions
    • old, used by Thread, ExecutorService
  • Callable:
    • returns a value
    • can throw checked exceptions

  1. Future vs CompletableFuture
  • Future:
    • .get() blocks
    • no callbacks
    • no composition
    • poor error handling
    • no manual completion (only by the ExecutorService)
  • CompletableFuture:
    • callbacks
    • composition (chaining, combining, etc.)
    • exception handling
    • manual completion

TODO: OOP questions, principles SOLID, DRY, etc. whatever goes on interviews these days

3. Spring & Spring Boot

  1. What is DI (dependency injection)? How does it work in Spring?
  • object's dependencies are provided from the outside, rather than the object creating them itself
  • loose coupling
  • better testability
  • Spring:
    • uses an IoC container (ApplicationContext), which instantiates beans, resolves dependencies, manages bean lifecycle
    • defining beans:
      • component scanning/class annotations:
        • @Component, @Service, @Repository, @Controller
        • @Configuration, @Bean for creating them if needed
      • XML configuration
      • Java configuration
    • injecting beans (@Autowired):
      • constructor injection (preferred): explicit, enables immutability, simple testing, no partially constructed objects
      • field injection
      • method injection

  1. @Component vs @Service vs @Repository
  • stereotype annotations
  • separation of layers
  • @Component:
    • generic
  • @Service, @Component mainly semantic
  • @Repository adds exception translation

  1. Spring Boot vs Spring
  • Spring Boot:
    • removes boilerplate code
    • auto-configuration based on classpath, application properties
    • opinionated defaults
    • embedded servers
    • starter dependencies ensure compatible versions
  1. How does autoconfiguration work internally?
  • @EnableAutoConfiguration:
    • loads config from config file in META-INF/...
    • beans are created if conditions match, guarded by @ConditionalOn... annotations
  • @SpringBootApplication is a meta annotation:
    • @EnableAutoConfiguration
    • @ComponentScan
    • @Configuration

  1. Spring MVC, REST APIs: @Controller vs @RestController, @ResponseBody?
  • @Controller:

    • marks a class as a controller
    • handles HTTP requests
    • returns views, view names (JSP, Thymeleaf, etc.)
  • @RestController (@Controller + @ResponseBody):

    • marks a class as a REST controller
    • handles HTTP requests
    • returns data (JSON, XML, etc.), usually JSON serialized with Jackson

  1. Exception handling in Spring
  • @ExceptionHandler:
    • handle specific exceptions
    • in controller, in global handler
  • @ControllerAdvice/@RestControllerAdvice:
    • global exception handling
    • multiple controllers
  • @ResponseStatus:
    • maps exception to HTTP status code
  • can use ResponseEntity object for more control
  • use custom exceptions for domain errors
  • avoid leaking internal exceptions
  • be consistent with the error formatting, status codes, semantics
  • log at the correct level
  • 4xx client, 5xx server errors

  1. JPA/Hibernate: @Entity vs @Embeddable vs @MappedSuperclass
  • @Entity:
    • mapped to a database table
    • has an id
    • can have lifecycle callbacks
  • @Embeddable + @Embedded:
    • can be embedded in another entity (columns in a row, a value object)
    • no id
    • no lifecycle callbacks
  • @MappedSuperclass:
    • hoist common attributes into a superclass
    • child classes inherit the attributes, but are mapped to separate tables
    • used for id, timestamps (audit fields), etc.

  1. Transaction management in Spring
  • @Transactional:
    • marks a method as transactional
    • Spring uses AOP proxies (like decorators in Python almost)
    • starts a transaction before the method is called
    • commits the transaction after the method returns
    • rolls back the transaction if an unchecked exception is thrown
    • propagation can be tuned (do nested transactions open new ones, or join an existing one, etc.)

  1. Messaging systems: what do they solve?
  • decouple components:
    • producers don't need to know who the consumers are, how many there are
  • reliability:
    • messages stored durably (usually)
    • failed consumers can reprocess queued up messages
  • scalability:
    • horizontal scaling by increasing consumer count, round robin

  1. Kafka vs RabbitMQ
  • Kafka:

    • distributed append-only log
    • message TTLs
    • consumers track offsets
    • topics and partitions
    • ordered per partition
    • message replay
    • event sourcing
    • stream processing
    • uses own protocol
    • "dumb broker, smart consumers"
  • RabbitMQ:

    • queue-based
    • focus on routing, topic based filtering
    • exchanges and queues
    • messages removed once ACKed
    • no replay
    • dead-letter queues
    • uses AMQP
    • "smart broker, dumb consumers"

4. Testing

How do you test a Spring Boot application?

  • unit tests:
    • mock dependencies
    • don't start the entire application context
  • integration tests:
    • can initialize the entire context with @SpringBootTest
    • can use slices:
      • @WebMvcTest
      • @DataJpaTest/@DataMongoTest
      • @RestClientTest
    • can use TestContainers, embedded DBs

5. Build tools

  • Maven:
    • declarative
    • convention over configuration
    • xml-based
    • linear lifecycle
    • no incremental builds by default
  • Gradle:
    • script-based (Groovy/Kotlin DSL)
    • more expressive
    • incremental builds
    • build cache
    • parallel execution

6. DevOps, Monitoring, Caching

Why use caching like Redis?

  • in memory, fast access to hot data paths
  • orders of magnitude faster than disk/network DB calls
  • reduces DB load
  • absorbs traffic spikes
  • cache patterns:
    • cache aside
    • write through (synchronous DB updates)
    • write behind (asynchronous DB updates)
  • good for rate limiting, distributed locks (TTL based leases)

DevOps and Monitoring questions left out...

Things like Docker, Kubernetes, Grafana, ELK stack, etc.