What happens if… — 20 Java interview scenarios 20 questions in 5 chapters

  1. 01Core Java and multithreading4 questions
  2. 02Java 8 streams4 questions
  3. 03Spring Boot4 questions
  4. 04Database and JPA4 questions
  5. 05Microservices, Kafka and security4 questions

Core Java and multithreading

Deadlock, equals/hashCode, shared counters, and Open/Closed design.

  • 1.1 Thread 1 locks A then B; thread 2 locks B then A, concurrently? Medium 1 min

    You can get a deadlock: each thread holds one lock and waits forever for the other. It is timing-dependent, so it often passes tests and fails in production. There is no exception; the threads sit blocked. I diagnose with a thread dump looking for a Java-level deadlock, and I fix it with a global lock order, tryLock with a timeout and back-off, or by collapsing to a single lock.

    Read the full answer
  • 1.2 Two Employee objects with identical data compared; equals() never overridden? Easy 1 min

    Object.equals is identity, so two different instances with the same fields are not equal. A HashSet keeps both, contains on a copy returns false, and map lookups with a newly built key miss. You must override equals and hashCode together, or use a record, which generates both from its components.

    Read the full answer
  • 1.3 Two threads print 1–100 (odd/even) with no synchronization? Medium 1 min

    Ordering is not guaranteed, so the output can interleave in any order. If they also share a counter without synchronization you get a data race: lost updates, duplicates or skips, and visibility bugs under the Java Memory Model. I fix it with a shared lock and wait/notify on a turn condition, two Conditions on a ReentrantLock, Semaphores that hand off, or an AtomicInteger turn check for a demo.

    Read the full answer
  • 1.4 New payment method added; PaymentService is a giant if-else on type? Medium 1 min

    You have to edit and retest the central class every time, which violates Open/Closed, grows fragile branches, and fails at runtime when a case is forgotten. I refactor to Strategy: one processor interface, one Spring bean per payment method, and a map from type to processor. A new method is a new class. With a sealed interface and pattern-matching switch, the compiler can flag missing cases instead.

    Read the full answer

Java 8 streams

Empty Optionals, duplicate keys, nulls in sorted, and single-use streams.

  • 2.1 filter then findAny then get finds no match — null or exception? Easy 1 min

    findAny returns an empty Optional, and calling get on that empty Optional throws NoSuchElementException with no value present. It never returns null from the stream. Prefer orElse, orElseGet, orElseThrow with a domain exception, or ifPresent. Also, findAny may return any matching element on a parallel stream, so use findFirst when encounter order matters.

    Read the full answer
  • 2.2 Word count with Collectors.toMap mapping each word to 1, and a word repeats? Easy 1 min

    You get IllegalStateException for a duplicate key when the two-argument collector sees the same word twice. Use the three-argument toMap with a merge function like Integer sum, or groupingBy with counting, which gives Long counts. Also remember toMap throws on null values, so filter or handle those first.

    Read the full answer
  • 2.3 Stream.concat of two lists then sorted, and one list contains null? Medium 1 min

    Concat itself is fine with null elements in either list, but sorted uses natural ordering, so comparing a null throws NullPointerException at the terminal operation because streams are lazy. Filter nulls out first, or sort with Comparator nullsFirst or nullsLast so nulls have a defined place in the result.

    Read the full answer
  • 2.4 collect invoked twice on the same stream? Easy 1 min

    The second call throws IllegalStateException saying the stream has already been operated upon or closed. Streams are single-use. Recreate the stream from the source, wrap creation in a Supplier, or collect once and reuse the result. If you need two results in one pass, use Collectors teeing.

    Read the full answer

Spring Boot

Missing beans, non-transactional side effects, hung HTTP clients, and lazy entities in controllers.

  • 3.1 Component removed from a class another bean Autowires? Easy 1 min

    Component scanning no longer registers that class, so the dependent bean cannot be created and startup fails with UnsatisfiedDependencyException or NoSuchBeanDefinitionException. Spring Boot's failure analyzer usually says a bean of that type could not be found. It still works if you declare the bean with a Bean method, or if the injection is optional through required false, Optional, or ObjectProvider.

    Read the full answer
  • 3.2 Transactional method writes a file, then the DB update fails? Hard 1 min

    The database work rolls back, but the file stays, because the filesystem is not a transactional resource. You end up inconsistent. Default rollback is only for unchecked exceptions and Error; a checked exception commits unless you set rollbackFor. Do the side effect after commit with a transactional event listener, write a temp file and move it on commit, compensate on rollback, or use an outbox for external effects.

    Read the full answer
  • 3.3 Service calls an external API with no timeout and the API hangs? Hard 1 min

    Request threads block, often indefinitely depending on the client defaults, which exhausts the Tomcat thread pool and connection pools so unrelated requests stop getting answers. If this call sits inside a database transaction, you also hold a DB connection open. Set explicit connect and read timeouts, add a circuit breaker and bulkhead, retry only with backoff on idempotent calls, and never call remote APIs inside a DB transaction.

    Read the full answer
  • 3.4 Controller returns a JPA entity with a lazy OneToMany? Hard 1 min

    Jackson walks getters and touches the lazy collection. With open-in-view off you get LazyInitializationException wrapped as a message conversion error. With Spring Boot's default open-in-view true it loads during rendering, which causes extra queries, N-plus-one risk, possible infinite recursion on bidirectional mappings, and leaked internal fields. Return DTOs or records, fetch what you need up front, and prefer open-in-view false.

    Read the full answer

Database and JPA

Huge result sets, N+1 fetches, second-highest salary ties, and LEFT JOIN filters.

  • 4.1 API loads one hundred thousand rows and returns them in one response? Medium 1 min

    You burn a lot of heap on entities, the persistence context, and the JSON buffer, which leads to GC pressure or out-of-memory, a slow query and transfer, timeouts, and a client that cannot render the payload. Paginate with Pageable, prefer keyset pagination for deep pages, project only the columns you need, cap the max page size, and for exports stream in a read-only transaction or write asynchronously to a file.

    Read the full answer
  • 4.2 Fetch one hundred orders, call getItems on each? Medium 1 min

    Classic N-plus-one: one query for the orders plus one query per order for items when the association is lazy. Fix it with join fetch or EntityGraph, watch pagination with collection fetches because Hibernate may paginate in memory, use batch fetching, or write a DTO query. Detect it with SQL logging, Hibernate statistics, or a query-count assertion in tests.

    Read the full answer
  • 4.3 Two employees tie for top salary; second highest via ORDER BY salary DESC LIMIT 1 OFFSET 1? Medium 1 min

    You get the other top-tied row again, not the second-highest distinct salary. Use distinct salaries with limit and offset, or a subquery for the max below the overall max, or dense rank equals two over salary descending, which also returns every employee at that salary. If there is no second distinct value, the result is empty or null.

    Read the full answer
  • 4.4 LEFT JOIN orders, then WHERE order status equals PAID? Medium 1 min

    It effectively becomes an inner join. Customers without matching orders have a null status, and null equals PAID is not true, so those customers disappear. To keep every customer, put the status filter in the join ON clause. Use where order id is null on purpose when you want an anti-join for customers with no orders.

    Read the full answer

Microservices, Kafka and security

Gateways, correlation IDs, at-least-once Kafka, and JWT logout.

  • 5.1 Remove the API gateway; frontend calls all six services directly? Medium 1 min

    The frontend now knows every service URL and contract, which couples clients to internals and makes versioning painful. You get many round trips on mobile, and auth, rate limiting, TLS, CORS, and logging get duplicated six times. Every service is publicly exposed, so the attack surface grows, and refactoring service boundaries breaks clients. Prefer a gateway or a backend-for-frontend per client type.

    Read the full answer
  • 5.2 Request fails three services deep, independent logs, no correlation ID? Medium 1 min

    You cannot stitch one request's logs across services, so debugging becomes timestamp guessing and mean time to recover goes up. Use distributed tracing with W3C traceparent propagation. In Spring Boot, Micrometer Tracing with an OpenTelemetry or Brave bridge propagates trace and span ids through instrumented clients and puts them in the log MDC. Centralize logs and return the trace id to clients on errors.

    Read the full answer
  • 5.3 Kafka consumer crashes after processing but before committing the offset? Hard 1 min

    On restart or rebalance the partition resumes from the last committed offset, so the message is processed again. That is at-least-once delivery. Effects must be idempotent: a dedupe table keyed by message or business id, upserts, or idempotent downstream APIs. Kafka transactions can give exactly-once inside Kafka, but external side effects still need idempotency. Committing before processing flips you to at-most-once and can lose work.

    Read the full answer
  • 5.4 User logs out but their JWT has not expired? Hard 1 min

    A self-contained JWT stays valid until its exp claim. Resource servers verify the signature locally and do not know about logout, so a stolen token still works. Mitigations are short-lived access tokens plus refresh tokens revoked on logout, a denylist of jti until expiry, opaque tokens with introspection, or a per-user token version check. Deleting the token only on the client is not revocation.

    Read the full answer