P
prepair.app
Start interview →
EnglishУкраїнськаРусскийDeutsch

Middle Java BackendJava backend interview questions

Middle · 2–4 years of experience

Java backend interviews cover core language semantics, collections, concurrency, Spring, and how you reason about the JVM. Below are the questions asked most often, each with a model answer. Middle: deeper understanding, optimization, and real-world situations.

Try it — no account needed
Preparing your question…

Topics to prepare

Core Java and OOP
Collections Framework
Concurrency and threads
Spring Boot and Spring Data
JVM, GC and memory
SQL and Hibernate

9 Middle-level questions with answers

1

How does HashMap work internally, and what changed in Java 8?

Answer

Entries live in an array of buckets indexed by a function of the key hash; collisions form a linked list in the same bucket. Java 8 added treeification: once a bucket holds more than eight entries it becomes a red-black tree, so worst-case lookup went from O(n) to O(log n). It also spreads the hash with h ^ (h >>> 16) so high bits influence the low-bit index.

2

What does volatile guarantee, and what does it not?

Answer

It guarantees visibility and ordering: a write is published to other threads immediately and reads are not cached in a register. It does not guarantee atomicity, so a volatile counter still loses increments, because ++ is read-modify-write and two threads can read the same value. Use volatile for a flag many threads read, and AtomicInteger or synchronized when the operation combines read and write.

3

Explain @Transactional propagation. When does REQUIRES_NEW matter?

Answer

Propagation decides what happens when a transactional method is called from inside another transaction. REQUIRED, the default, joins the existing one — so a rollback anywhere rolls back everything. REQUIRES_NEW suspends the outer transaction and starts its own, which is what you want for an audit log or a notification that must survive the caller failing. The classic bug is expecting REQUIRED to isolate a failure when it cannot.

4

You see the N+1 problem in a Hibernate-backed endpoint. How do you find and fix it?

Answer

You find it by turning on SQL logging and counting queries for one request — the signature is one select followed by hundreds of near-identical ones. It happens when you load parents and then touch a lazy collection on each. Fixes are JOIN FETCH in JPQL, an entity graph, @BatchSize to fetch in groups, or a projection that selects only the fields the response needs. Switching to EAGER is not a fix; it moves the problem.

5

What is the difference between Stream and a for loop, and when is a loop better?

Answer

A stream describes a pipeline of lazy operations executed by a terminal call, which keeps filtering and mapping readable. A loop is better in a hot path where the abstraction costs measurable time, when the logic has side effects, and when a break in the middle would express it more clearly than a takeWhile. Parallel streams are the real trap — they help only for large CPU-bound work and usually hurt otherwise.

6

A service is slow and CPU is low. Where do you look?

Answer

Low CPU with poor throughput points at waiting rather than computing: blocking IO, an exhausted connection pool, lock contention, or an external call without a timeout. Take a thread dump and see what threads are actually parked on. Connection pool starvation is the most common culprit, and it usually traces back to a transaction held open across a network call.

7

What is the difference between Spring Boot auto-configuration and a plain @Configuration class?

Answer

Auto-configuration is conditional configuration shipped by a starter: classes annotated with @ConditionalOnClass or @ConditionalOnMissingBean that apply only when a dependency is on the classpath and you have not defined the bean yourself. That last part is what makes it feel magical and predictable at once — your own bean always wins, which is how you override any default.

8

What is the difference between `wait()`, `sleep()` and `join()`?

Answer

sleep pauses the current thread and keeps any lock it holds — which is how you deadlock while looking innocent. wait releases the monitor and parks the thread until notify, and it can only be called inside a synchronized block for that reason. join waits for another thread to finish. wait and notify belong to Object rather than Thread because the lock belongs to the object.

9

What does `transient` do, and where does serialization bite?

Answer

transient excludes a field from serialization, so on deserialization it comes back as the type's default. You use it for anything derived, anything huge, and anything secret — a password or a live connection has no business in a byte stream. The wider trap is that serialization freezes your class shape into a format: change the fields and old data fails to read unless serialVersionUID and compatibility were planned, which is why most teams use JSON or protobuf instead.

🦎

Reading answers is not enough

In a real interview you speak under pressure. Cam asks these same questions, scores every answer, and shows exactly what to fix.

Practice a Middle Java Backend interview →
Free · 3 interviews per month

Other levels — Java Backend

Junior Java BackendSenior Java BackendAll Java Backend questions

Other specializations

🔍Middle Manual QA🤖Middle QA Automation🐍Middle Python Backend🐘Middle PHP Backend🦫Middle Go Backend🟢Middle Node.js Backend💎Middle Ruby on Rails🟣Middle .NET Backend Developer🔷Middle C++🟨Middle JavaScript