These are the Java questions that come up again and again in interviews in India in 2026, from service companies to product startups. Each one has a short answer you could say out loud in about 30 seconds, and the points interviewers listen for.
How to use this list: don't memorise the answers. Read one, close the page, and say your own answer out loud. If you can't say it in 30 seconds, you don't know it well enough yet.
Core Java interview questions
Why must you override hashCode when you override equals?
Hash-based collections find an object by its hashCode first, then check equals. If two objects are equal but return different hash codes, a HashMap or HashSet looks in the wrong bucket: you get duplicates in a set, or get() returns null for a key you just put. So the contract is: equal objects must have equal hash codes. Override both together, using the same fields.
What the interviewer listens for: Equal objects, equal hash, Breaks HashMap/HashSet.
Why are Strings immutable in Java?
Strings are immutable so they can be safely shared: the JVM keeps a string pool and many references point to one String object. Immutability also makes them thread-safe without locking, safe to use as HashMap keys (the hash is cached), and secure for things like file paths and class names that mustn't change after a check.
What the interviewer listens for: String pool, Security / thread safety, Hash caching.
What is the difference between the JDK, the JRE and the JVM?
The JVM runs compiled bytecode on any platform. The JRE is the JVM plus the standard libraries needed to run Java programs. The JDK is the JRE plus development tools like the compiler (javac) and debugger, needed to build programs.
What the interviewer listens for: JVM runs bytecode, JRE = JVM + libraries, JDK = JRE + tools.
Is Java pass-by-value or pass-by-reference?
Java is always pass-by-value. For objects, the value passed is a copy of the reference, so a method can change the object's fields, but reassigning the parameter doesn't affect the caller's variable.
What the interviewer listens for: Always pass-by-value, Object references are copied.
What does the final keyword do on a variable, a method and a class?
A final variable can be assigned only once. A final method can't be overridden by subclasses. A final class can't be extended at all, like String. Note that a final reference to an object still lets you change the object's contents.
What the interviewer listens for: Variable can't be reassigned, Method can't be overridden, Class can't be extended.
What does static mean in Java, and when would you use it?
A static member belongs to the class, not to any instance, so all objects share it and you can use it without creating an object. Use it for constants, utility methods like Math.max, and factory methods. Avoid static mutable state: it's shared globally and hard to test.
What the interviewer listens for: Belongs to the class, Use for utilities or constants.
OOP interview questions
Explain the four pillars of object-oriented programming with an example.
Encapsulation keeps data private and exposes behaviour through methods, like a BankAccount whose balance changes only through deposit and withdraw. Inheritance lets a SavingsAccount reuse Account. Polymorphism lets code call account.calculateInterest() and get the right behaviour for each type. Abstraction exposes what an object does, not how, through interfaces and abstract classes.
What the interviewer listens for: Encapsulation, Inheritance, Polymorphism, Abstraction.
Interface versus abstract class: when do you use which?
An interface is a contract: what a class can do, with no state. A class can implement many. An abstract class shares code and state between closely related classes. A class can extend only one. Use an interface for capabilities across unrelated types (Comparable, Runnable), an abstract class when subclasses share real implementation.
What the interviewer listens for: Contract vs shared code, Multiple interfaces.
Pick two SOLID principles and show how you've applied them.
Single responsibility: one reason to change. For example, I split a ReportService that both fetched data and built PDFs into two classes, so a PDF change no longer touched data code. Dependency inversion: depend on abstractions, so I injected a PaymentGateway interface instead of a concrete Razorpay client, which let us add a second provider and mock it in tests. The other three are open-closed, Liskov substitution and interface segregation.
What the interviewer listens for: Named principles, Real example.
Which design pattern have you used most, and why?
I've used the Builder pattern most, for objects with many optional fields like an API request or a test fixture: it keeps construction readable and the object immutable. Strategy is a close second: choosing a pricing or payment algorithm at runtime without if-else chains. Name the pattern, where you used it, and what problem it solved.
What the interviewer listens for: Named pattern, Where and why.
Method overloading versus overriding?
Overloading is several methods with the same name and different parameters in one class, chosen at compile time. Overriding is a subclass providing its own version of an inherited method with the same signature, chosen at runtime based on the object's actual type: that's runtime polymorphism.
What the interviewer listens for: Overloading: same name, different parameters, Overriding: subclass replaces behaviour.
Composition or inheritance: which do you prefer and why?
Prefer composition: build behaviour by holding other objects (has-a) and delegating to them. It's flexible and avoids the fragile base class problem, where a change in a parent breaks subclasses. Use inheritance only for a true is-a relationship where the subclass can be used anywhere the parent is.
What the interviewer listens for: Prefer composition, Inheritance couples tightly.
Collections interview questions
What's the difference between HashMap and ConcurrentHashMap?
HashMap is not thread-safe: two threads writing at once can lose updates or corrupt the map. ConcurrentHashMap is built for concurrent use: reads don't lock, and writes lock only one bucket (using compare-and-swap where it can), so many threads work in parallel instead of waiting on one lock. It also doesn't allow null keys or values, so 'absent' is never ambiguous. Use ConcurrentHashMap whenever a map is shared between threads.
What the interviewer listens for: Thread safety, How it locks, Null keys.
ArrayList versus LinkedList: when would you use each?
ArrayList is backed by an array: get by index is O(1) and it's cache-friendly, but inserting in the middle shifts elements. LinkedList makes insertion and removal at known positions cheap but random access is O(n). In practice ArrayList is the default. ArrayDeque beats LinkedList for queues.
What the interviewer listens for: ArrayList: fast random access, LinkedList: cheap insert/remove at ends, ArrayList is usually better.
How does a HashMap work internally?
The key's hashCode is spread and used to pick a bucket in an array. Keys in the same bucket form a linked list, which becomes a balanced tree when it grows long, so lookups stay fast. equals finds the exact key in the bucket. When the map is 75% full (the load factor), the array doubles and entries are rehashed.
What the interviewer listens for: Hash picks a bucket, Collisions chain or treeify, Resizes at load factor.
HashSet, LinkedHashSet and TreeSet: what's the difference?
All three hold unique elements. HashSet has no order and the fastest operations. LinkedHashSet keeps insertion order. TreeSet keeps elements sorted (natural order or a Comparator), with O(log n) operations.
What the interviewer listens for: HashSet: no order, LinkedHashSet: insertion order, TreeSet: sorted.
Comparable versus Comparator: when do you use each?
Comparable defines a class's natural ordering through compareTo, inside the class itself, like sorting employees by ID. Comparator is a separate object, so you can define many orderings without changing the class, like by name or by salary, often as a lambda: Comparator.comparing(Employee::getSalary).
What the interviewer listens for: Comparable: natural order in the class, Comparator: separate, many orders.
What is a fail-fast iterator, and how do you avoid ConcurrentModificationException?
A fail-fast iterator throws ConcurrentModificationException if the collection is structurally changed while you iterate, other than through the iterator. Remove items with iterator.remove() or removeIf, collect changes and apply them after the loop, or use a concurrent collection like CopyOnWriteArrayList or ConcurrentHashMap, whose iterators don't fail.
What the interviewer listens for: Detects modification while iterating, Use iterator.remove or concurrent collections.
Exceptions interview questions
Checked versus unchecked exceptions: what's the difference, and which do you prefer?
Checked exceptions (like IOException) must be caught or declared with throws, so the compiler forces callers to handle them. Unchecked exceptions extend RuntimeException (like NullPointerException) and aren't checked at compile time. Use checked exceptions for recoverable conditions the caller should handle, unchecked for programming errors. Many teams prefer unchecked exceptions with clear handling at the boundary.
What the interviewer listens for: Compile-time check, RuntimeException.
What is try-with-resources, and why use it?
try-with-resources declares resources that implement AutoCloseable, like streams and connections, and closes them automatically when the block ends, even if an exception is thrown. It replaces error-prone finally blocks, prevents leaks, and keeps suppressed exceptions instead of hiding the original one.
What the interviewer listens for: Closes resources automatically, No leaks even on exceptions.
When would you create a custom exception, and checked or unchecked?
Create one when a domain error needs its own meaning and handling, like InsufficientBalanceException, so callers can catch it specifically and the API can map it to the right response. Most teams make them unchecked (extend RuntimeException) and handle them at a boundary, like a Spring @ControllerAdvice.
What the interviewer listens for: Carry domain meaning, Usually unchecked.
JVM &. Memory interview questions
How does garbage collection work in Java, in simple terms?
The garbage collector frees objects that nothing references any more. The heap is split into generations: new objects go to the young generation, which is collected often and quickly because most objects die young. Objects that survive are promoted to the old generation, collected less often. Collectors like G1 (the default) and ZGC do most of this work alongside the application to keep pauses short.
What the interviewer listens for: Unreachable objects, Generations, A collector.
How would you find a memory leak in a Java service running in production?
First confirm it: watch heap usage after full GCs climbing over time in metrics or GC logs. Then take a heap dump (jmap or -XX:+HeapDumpOnOutOfMemoryError) and open it in Eclipse MAT or VisualVM. Look at the dominator tree for what retains the most memory: usually a growing cache or static collection, listeners that are never removed, or ThreadLocals in a thread pool. Fix the reference, then verify heap use stays flat.
What the interviewer listens for: Heap dump, Analyse it, Watch metrics.
What's stored on the heap and what's on the stack?
Each thread has its own stack holding method frames: local variables, primitives and references. Objects created with new live on the heap, which all threads share and the garbage collector manages. StackOverflowError means a stack ran out (usually deep recursion). OutOfMemoryError usually means the heap did.
What the interviewer listens for: Stack: frames and locals, Heap: objects, Stack per thread.
How does class loading work in Java?
Classes are loaded when first used. Class loaders follow parent delegation: a loader first asks its parent (bootstrap, then platform, then application loader), so core classes always come from the JDK. Loading is followed by linking (verification, preparation) and initialisation, when static blocks run.
What the interviewer listens for: Loaded lazily, Parent delegation.
Streams &. Java 8+ interview questions
When would you use Java streams, and when would a plain loop be better?
Streams are good for declarative pipelines: filter, map, group and collect read clearly and are easy to parallelise. A plain loop is better when you need to break early, handle checked exceptions, mutate state, use indexes, or when performance on a hot path matters and the stream's overhead shows up. Readability decides most of the time.
What the interviewer listens for: Readable pipelines, Loop is better when.
What is a functional interface, and how do lambdas relate to it?
A functional interface has exactly one abstract method, like Runnable, Comparator, Function or Predicate. A lambda is a short way to implement that method: list.removeIf(x ->. X <. 0) passes a Predicate. Method references like String::trim are a shorter form of the same thing.
What the interviewer listens for: One abstract method, Lambda implements it, Examples.
What is Optional for, and how should you use it?
Optional makes 'there may be no value' explicit instead of returning null. Use it as a return type, then map, orElse, orElseThrow or ifPresent instead of null checks. Don't use it for fields or parameters, and don't call get() without checking.
What the interviewer listens for: Avoid null for missing values, Return type, not fields, orElse / map.
map versus flatMap in streams?
map transforms each element into exactly one new element. flatMap transforms each element into a stream and flattens them into one stream, for example turning a list of orders into a stream of all their items: orders.stream().flatMap(o ->. O.getItems().stream()).
What the interviewer listens for: map: one to one, flatMap: flattens nested streams.
How would you group a list of employees by department with streams?
employees.stream().collect(Collectors.groupingBy(Employee::getDepartment)) gives a Map from department to a list of employees. Add a downstream collector for summaries, like groupingBy(Employee::getDepartment, Collectors.counting()) for headcount, or averagingDouble(Employee::getSalary) for the average salary.
What the interviewer listens for: groupingBy, Downstream collector.
Multithreading interview questions
How would you make a counter safe when many threads update it?
count++ isn't atomic: it's read, add, write, so two threads can read the same value and lose an update (a race condition). Use AtomicInteger (or LongAdder under heavy contention), which updates with compare-and-swap, or protect the counter with synchronized or a Lock. Atomic types are usually the simplest and fastest.
What the interviewer listens for: Atomic types, Or locking, Why ++ is unsafe.
Process versus thread: what's the difference?
A process has its own memory space. Threads inside a process share memory. So threads are lighter and cheaper to switch between, and can share data directly, but a bug in one thread can corrupt shared state or crash the whole process. Processes are isolated: one crashing doesn't take the others down, at the cost of more memory and slower communication.
What the interviewer listens for: Own memory vs shared, Cost of switching, Crash isolation.
synchronized versus volatile: what's the difference?
volatile guarantees visibility: every thread sees the latest write to the variable, but compound actions like count++ are still not atomic. synchronized gives both visibility and mutual exclusion: only one thread runs the block at a time. Use volatile for simple flags, synchronized or atomic types for read-modify-write.
What the interviewer listens for: volatile: visibility only, synchronized: mutual exclusion too.
Why use an ExecutorService instead of creating threads yourself?
Creating a thread per task is expensive and unbounded. An ExecutorService reuses a pool of threads, limits how many run at once, queues the rest, returns Futures for results and exceptions, and shuts down cleanly. Size the pool for the work: CPU-bound around the core count, I/O-bound larger.
What the interviewer listens for: Reuses a thread pool, Controls concurrency and queuing, Futures and shutdown.
What is a deadlock, and how do you prevent one?
A deadlock is when two or more threads each hold a lock the other needs, so all wait forever. Prevent it by always acquiring locks in the same global order, holding locks briefly, using tryLock with a timeout, or avoiding nested locks altogether with higher-level concurrency tools. Thread dumps show deadlocks when they happen.
What the interviewer listens for: Threads wait on each other's locks, Lock in a fixed order, Timeouts / tryLock.
What is CompletableFuture, and when have you used it?
CompletableFuture represents an async result you can chain without blocking: thenApply, thenCompose, and allOf to run independent calls in parallel and combine them, with exceptionally or handle for errors. For example, calling the pricing and inventory services in parallel and merging the results cut a page's response time roughly in half.
What the interviewer listens for: Async pipeline, Combine calls, Handle errors.
What are the states of a thread in Java?
NEW before start(). RUNNABLE when running or ready to run. BLOCKED waiting for a monitor lock. WAITING or TIMED_WAITING when waiting on another thread or a timeout (wait, join, sleep). TERMINATED when run() finishes.
What the interviewer listens for: New and runnable, Blocked / waiting, Terminated.
Practise these Java questions out loud
Our Rapid fire round asks 10 Java questions, gives you 5 seconds to think and 30 seconds to answer, then shows the key points you covered, your filler words and your pace. Free, 2 sessions a day.