HireHireInterview Quizzes › Java Developer

Java Developer Interview Questions

Think you're ready? These are the questions that actually decide Java Developer interviews. Warm up on Easy — then face the Hard round, where 95% of candidates crumble. 30 questions across 3 levels, instant score, completely free.

30Questions
3Difficulty levels
95%Fail the hard round
FreeInstant score
Easy
Warm-up · 10 Qs
Medium
Practical · 10 Qs
Hard
Brutal · 10 Qs
⚡ Take the Java Developer quiz — get your score →

The Java Developer interview questions

Below are the real questions, grouped by difficulty. Expand any one to reveal the correct answer and why — or take the timed quiz for a score you can share. Can you clear the Hard round?

Easy round 10 questions

What is the output of: System.out.println("5" + 3 + 2); in Java?
  • A. 532 ✓
  • B. 10
  • C. 55
  • D. Compilation error
Correct answer: A. The + operator is left-associative and string concatenation with a String operand converts both 3 and 2 to characters, producing "532".
In Java, what happens when you compare two non-interned Strings using == ?
  • A. It compares their character contents
  • B. It compares their reference (memory address) identity ✓
  • C. It always returns true for equal text
  • D. It throws a NullPointerException
Correct answer: B. The == operator compares object references, not content, so two distinct String objects with the same text return false unless equals() is used.
Which collection maintains insertion order and allows duplicate elements?
  • A. HashSet
  • B. TreeSet
  • C. ArrayList ✓
  • D. HashMap
Correct answer: C. ArrayList is an ordered List implementation that preserves insertion order and permits duplicate elements.
What is the key difference between checked and unchecked exceptions in Java?
  • A. Checked exceptions must be declared or handled at compile time; unchecked need not be ✓
  • B. Unchecked exceptions must always be caught with try-catch
  • C. Checked exceptions extend RuntimeException
  • D. Unchecked exceptions cannot be thrown manually
Correct answer: A. Checked exceptions (subclasses of Exception excluding RuntimeException) are enforced by the compiler to be caught or declared, while unchecked exceptions are not.
In Spring, what does the @Autowired annotation do?
  • A. Creates a new database connection pool
  • B. Injects a matching bean dependency from the application context ✓
  • C. Marks a method as a REST endpoint
  • D. Schedules a method to run periodically
Correct answer: B. @Autowired enables automatic dependency injection by resolving and wiring a matching bean from the Spring container.
What is the correct way to safely handle a resource like a database connection so it is always closed?
  • A. Use a finally-only block without closing
  • B. Rely on the garbage collector to close it
  • C. Use a try-with-resources statement ✓
  • D. Call System.gc() after using it
Correct answer: C. try-with-resources automatically closes any resource implementing AutoCloseable when the block exits, even on exception.
Which HTTP method is idempotent and typically used to update or replace a resource in a REST API?
  • A. POST
  • B. PUT ✓
  • C. PATCH
  • D. CONNECT
Correct answer: B. PUT is idempotent because repeating the same request produces the same server state, making it suitable for full resource replacement.
What does the 'final' keyword mean when applied to a variable in Java?
  • A. The variable can only be accessed within its class
  • B. The variable's value cannot be reassigned after initialization ✓
  • C. The variable is automatically static
  • D. The variable is stored in the database
Correct answer: B. A final variable can be assigned only once, so its reference or primitive value cannot be changed after initialization.
In a multithreaded Java program, which keyword ensures a variable's changes are visible across threads immediately?
  • A. transient
  • B. volatile ✓
  • C. synchronized
  • D. static
Correct answer: B. The volatile keyword guarantees that reads and writes go directly to main memory, ensuring visibility of changes across threads.
What is the default value of an uninitialized int instance field in Java?
  • A. null
  • B. 0 ✓
  • C. undefined
  • D. -1
Correct answer: B. Uninitialized numeric instance fields default to 0 (int specifically to 0), unlike object references which default to null.

Medium round 10 questions

You have a List<String> and want to remove all elements equal to "x" while iterating. Which approach avoids a ConcurrentModificationException?
  • A. Loop with an enhanced for-each and call list.remove("x") inside
  • B. Use list.removeIf(s -> s.equals("x")) ✓
  • C. Iterate by index from 0 upward and remove matching elements
  • D. Stream the list and call forEach with list.remove inside
Correct answer: B. removeIf safely removes matching elements without a ConcurrentModificationException, unlike modifying a list during for-each iteration.
What does the following print? String a = "hi"; String b = new String("hi"); System.out.println(a == b);
  • A. true
  • B. false ✓
  • C. It throws a NullPointerException
  • D. It does not compile
Correct answer: B. new String() creates a distinct object on the heap, so == compares references and returns false even though the contents are equal.
In a Spring Boot application, which annotation is most appropriate for a class that holds business logic and should be injected into controllers?
  • A. @Component on a plain class only
  • B. @Service ✓
  • C. @Repository
  • D. @Controller
Correct answer: B. @Service is the semantic stereotype for a business-logic bean, making it discoverable for dependency injection into controllers.
You override equals() in a class used as a HashMap key but forget to override hashCode(). What is the most likely consequence?
  • A. Compilation fails because both must be overridden together
  • B. Lookups may fail to find entries even when an equal key exists ✓
  • C. Every key collides into a single bucket, but lookups still work
  • D. hashCode() is automatically generated to match equals()
Correct answer: B. Unequal hashCodes for equal objects can route them to different buckets, so the map may not find an entry with an equal key.
Which statement about a try-with-resources block is correct?
  • A. It requires an explicit finally block to close the resource
  • B. The resource must implement AutoCloseable and is closed automatically ✓
  • C. It suppresses all exceptions thrown inside the block
  • D. Resources are closed in the same order they were declared
Correct answer: B. try-with-resources closes any resource implementing AutoCloseable automatically, in reverse order of declaration, without a manual finally.
What is the result of Integer.valueOf(127) == Integer.valueOf(127) compared to Integer.valueOf(128) == Integer.valueOf(128)?
  • A. Both are true
  • B. Both are false
  • C. The first is true, the second is false ✓
  • D. The first is false, the second is true
Correct answer: C. Integer caches boxed values from -128 to 127, so 127 returns the same cached reference (true) while 128 creates new objects (false).
In JPA/Hibernate, you load a list of orders and access each order's lazy-loaded items in a loop, firing one query per order. What is this problem called?
  • A. Cartesian product explosion
  • B. The N+1 select problem ✓
  • C. Dirty read anomaly
  • D. Connection pool starvation
Correct answer: B. Executing one additional query per parent entity to fetch its children is the classic N+1 select problem, typically solved with a join fetch.
Which Maven command compiles the project, runs tests, and installs the artifact into your local repository?
  • A. mvn compile
  • B. mvn package
  • C. mvn install ✓
  • D. mvn deploy
Correct answer: C. mvn install runs all lifecycle phases up to and including install, which places the built artifact in the local ~/.m2 repository.
You want a thread-safe counter incremented by many threads without using synchronized blocks. Which is the best fit?
  • A. A volatile int field
  • B. An AtomicInteger ✓
  • C. A plain long field
  • D. A HashMap<String, Integer>
Correct answer: B. AtomicInteger provides lock-free atomic increment via incrementAndGet(), whereas volatile alone does not make the read-modify-write of ++ atomic.
Given a stream of employees, which collector groups them into a Map keyed by department?
  • A. Collectors.toMap(Employee::getDept, e -> e)
  • B. Collectors.groupingBy(Employee::getDept) ✓
  • C. Collectors.partitioningBy(Employee::getDept)
  • D. Collectors.mapping(Employee::getDept, Collectors.toList())
Correct answer: B. Collectors.groupingBy produces a Map<Dept, List<Employee>> grouping elements by the classifier, which is exactly what is needed here.

Hard round 10 questions

A team ships a lazy singleton using double-checked locking, but the `instance` field is a plain (non-volatile) `Object`. Under load on a multi-core JVM, another thread occasionally sees a non-null `instance` whose fields are still at their default values. What is the precise root cause?
  • A. The compiler removes the inner null check via lock elision, so two threads run the constructor concurrently
  • B. Without volatile, the write publishing the reference can be reordered before the constructor's field writes complete, so a reader sees a non-null but partially-constructed object ✓
  • C. The synchronized block only guarantees mutual exclusion, so the second thread always re-runs the constructor and overwrites the first instance
  • D. HotSpot never caches object references in registers, so the issue is purely a heap-visibility flush that a memory barrier on read would fix
Correct answer: B. Without volatile there is no happens-before edge, so the reference publication can be reordered ahead of the constructor's writes, exposing a partially-constructed object to another thread.
Consider `private volatile int[] data = new int[10];` accessed by many threads that do `data[i]++` concurrently on distinct-looking but sometimes overlapping indices. Why does marking the array reference `volatile` fail to make these updates thread-safe?
  • A. volatile only establishes visibility/ordering for reads and writes of the reference itself, not for reads/writes of the array's elements, which remain unsynchronized ✓
  • B. volatile arrays are copied on every write, so the increment operates on a stale snapshot
  • C. volatile forces every element access through a lock, but the lock is reentrant so nested increments corrupt the counter
  • D. The JIT strips volatile from array fields during escape analysis, silently downgrading it to a plain field
Correct answer: A. The volatile modifier applies to the reference variable, not the elements; per-element mutations have no memory-model guarantees and the `++` is also non-atomic.
Two threads run this code with shared `int x = 0; boolean ready = false;` — Thread A: `x = 42; ready = true;` — Thread B: `if (ready) System.out.println(x);`. Neither variable is volatile or synchronized. Which statement about permitted outcomes is correct under the JMM?
  • A. B can only ever print 42, because assignment order in A is preserved by program order across threads
  • B. B can print 0 or observe ready==true before x==42, because without a happens-before relation A's writes may be observed out of order ✓
  • C. The program is guaranteed to deadlock since ready is read without a lock
  • D. B will always block until ready becomes true because reads of shared booleans are implicitly synchronized
Correct answer: B. Absent a happens-before edge, Thread B may observe `ready==true` while still reading the stale `x==0` due to permitted reordering/visibility gaps.
You have a producer-consumer using `wait()`/`notify()`. A reviewer insists the consumer's `wait()` must sit inside `while (queue.isEmpty())` rather than `if (queue.isEmpty())`. What is the strongest technical justification?
  • A. `if` would hold the monitor during wait, whereas `while` releases it, preventing a deadlock
  • B. A thread returning from wait may find the condition false again due to spurious wakeups or another consumer having drained the item, so the predicate must be re-checked in a loop ✓
  • C. `notify()` only wakes threads that used `while`, so `if`-based waiters are never scheduled
  • D. `while` guarantees FIFO fairness among waiters, which `if` cannot provide
Correct answer: B. wait() can return without the intended condition holding (spurious wakeups, or another thread consumed the item), so the guard must be re-tested in a loop.
A `@Service` bean has a public `outer()` method (no annotation) that calls `this.inner()`, where `inner()` is annotated `@Transactional(propagation = REQUIRES_NEW)`. At runtime `inner()` runs in no transaction at all. Why?
  • A. REQUIRES_NEW is ignored unless the outer method is also @Transactional, so propagation silently downgrades to SUPPORTS
  • B. The self-invocation `this.inner()` bypasses the Spring CGLIB/JDK proxy, so the transactional advice around inner() never fires ✓
  • C. REQUIRES_NEW requires an XA datasource; without one Spring skips transaction creation and logs a warning
  • D. Spring caches the transaction status per thread, and since outer() opened none, inner() inherits the empty context permanently
Correct answer: B. Transactional advice lives on the proxy; an internal `this.` call goes straight to the target instance, skipping the proxy and thus all propagation handling.
A production service running Hibernate returns a `User` entity from a `@Transactional` service method to a controller, which then accesses `user.getOrders()` (a `LAZY` collection) to render JSON. Users get intermittent `LazyInitializationException`. What is the correct root-cause explanation?
  • A. The collection was mapped EAGER, so Hibernate throws when it detects a redundant fetch in the view layer
  • B. The persistence context/session closed when the transactional method returned, so the proxy has no session to initialize the collection during controller-layer access ✓
  • C. The exception occurs because getOrders() triggers an N+1 query that exceeds the connection pool, timing out the fetch
  • D. Jackson serializes the collection on a different thread that lacks the ThreadLocal session, unlike single-threaded access which succeeds
Correct answer: B. Lazy collections need an open session to initialize; once the transactional boundary closes the session, touching the uninitialized proxy later throws LazyInitializationException.
A REST endpoint calls a downstream payment API. On timeout your client retries. Occasionally a customer is charged twice. Which approach most directly prevents duplicate side effects while keeping at-least-once retry semantics?
  • A. Switch retries to at-most-once by disabling them entirely, accepting occasional lost charges
  • B. Attach a client-generated idempotency key to each logical request so the server deduplicates retries of the same operation ✓
  • C. Wrap the call in a distributed lock so only one node can call the payment API at a time
  • D. Increase the client socket timeout so responses always arrive before a retry is triggered
Correct answer: B. An idempotency key lets the server recognize a retried request as the same logical operation and return the original result instead of charging again.
You must reliably publish an event to Kafka whenever a row is written to your SQL database, but a crash between the DB commit and the Kafka send can lose events (dual-write problem). Which pattern correctly guarantees the event is not lost?
  • A. Send to Kafka first, then commit the DB row, so the broker is the source of truth
  • B. Use the Outbox pattern: write the event into an outbox table in the same DB transaction, then a separate relay reads and publishes it, retrying until acknowledged ✓
  • C. Wrap both the DB commit and the Kafka producer.send() in a single synchronized block
  • D. Enable Kafka idempotent producer, which retroactively rolls back the DB row if the send fails
Correct answer: B. The Outbox pattern makes the event write atomic with the business data (one DB transaction), and a separate relay guarantees at-least-once delivery to Kafka.
A latency-sensitive service (P99 pause budget ~10ms) runs on a 64GB heap and suffers multi-hundred-millisecond stop-the-world pauses during full GCs with the Parallel collector. Which change best fits the requirement, and why?
  • A. Switch to ZGC, because it performs concurrent marking and relocation to keep pauses sub-millisecond largely independent of heap size ✓
  • B. Switch to the Serial collector to reduce GC thread contention on the large heap
  • C. Keep Parallel GC but set -XX:MaxGCPauseMillis=10, which converts full GCs into concurrent cycles
  • D. Shrink the heap to 4GB so full GCs complete within the 10ms budget
Correct answer: A. ZGC is designed for low, near-constant pause times that scale to large heaps by doing marking and relocation concurrently, matching a tight P99 pause goal.
A mutable object is used as a key in a `HashMap`. After insertion, code mutates a field that participates in `equals`/`hashCode`. Later `map.get(sameKeyReference)` returns null even though the entry is clearly present. What is the precise mechanism?
  • A. HashMap rehashes on every mutation, so the entry was moved to a bucket the key no longer maps to
  • B. The entry was stored in the bucket derived from the original hashCode; the mutated key now hashes to a different bucket, so the lookup probes the wrong bucket and misses the entry ✓
  • C. equals() now returns false against itself, so identity comparison inside get() fails
  • D. Treeification converted the bucket to a red-black tree keyed by the old hash, corrupting the lookup index
Correct answer: B. The entry stays in the bucket chosen at insertion time; a mutated hashCode routes get() to a different bucket, so it never finds the entry.

Prep for another role

Questions are original, written and independently verified for HireHire's role interview quizzes. They reflect the kind of knowledge Java Developer interviews test, not any specific company's questions. HireHire maps live tech & IT jobs across India, updated regularly. Last updated: July 2026.