What happens if… — 20 Java interview scenarios 20 questions in 5 chapters
- 01Core Java and multithreading4 questions
- 02Java 8 streams4 questions
- 03Spring Boot4 questions
- 04Database and JPA4 questions
- 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 answer1.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 answer1.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 answer1.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 answer2.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 answer2.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 answer2.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 answer3.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 answer3.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 answer3.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 answer4.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 answer4.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 answer4.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 answer5.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 answer5.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 answer5.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