Java Interview Questions
Java is the most common programming topic in backend and full-stack interviews. These are the questions interviewers actually ask, grouped by theme and tagged by experience level, with concise answers you can speak confidently.
105 questions with concise, interview-ready answers.
Java Basics
1. What is the difference between JDK, JRE, and JVM? Fresher
The JVM (Java Virtual Machine) is the runtime engine that executes Java bytecode and is platform-specific. The JRE (Java Runtime Environment) is the JVM plus core libraries needed to run Java applications. The JDK (Java Development Kit) is the JRE plus development tools like the compiler (javac) and debugger, so you need it to compile and build Java code.
2. Why is Java called platform-independent? Fresher
The Java compiler turns source code into bytecode rather than native machine code. That bytecode runs on any platform that has a JVM, following the "write once, run anywhere" principle. The JVM itself is platform-specific, but your compiled code is not.
3. Is Java fully object-oriented? Fresher
No, and interviewers ask this to see whether you have thought about it. Java has eight primitive types (byte, short, int, long, float, double, char, boolean) that are not objects, so it is not purely object-oriented in the way Smalltalk or Ruby are. Everything else is an object, and autoboxing hides the distinction most of the time.
4. What are the eight primitive data types in Java? Fresher
byte (8-bit), short (16-bit), int (32-bit), long (64-bit), float (32-bit), double (64-bit), char (16-bit Unicode), and boolean. All are signed except char. They are stored by value rather than by reference, which is why they cannot be null and why each has a wrapper class.
5. What is autoboxing and unboxing? Fresher
Autoboxing is the automatic conversion of a primitive to its wrapper object (int to Integer); unboxing is the reverse. It makes primitives usable in collections, which only hold objects. The cost is hidden allocation in loops and a NullPointerException risk when unboxing a null Integer.
6. What is the difference between == and equals() in Java? Fresher
The == operator compares references for objects, checking whether two variables point to the same object in memory (for primitives it compares values). The equals() method compares logical equality of content, and classes like String and Integer override it to compare actual values. As a rule, use == for primitives and equals() for objects.
7. What is the difference between final, finally, and finalize? Fresher
final is a keyword: a final variable cannot be reassigned, a final method cannot be overridden, and a final class cannot be extended. finally is a block that always runs after a try/catch, typically to release resources. finalize() was a method called by the garbage collector before reclaiming an object, but it is deprecated and unreliable, so cleanup should use try-with-resources or explicit close instead.
8. What is the difference between static and instance members? Fresher
A static member belongs to the class and is shared by every instance; it is initialised once when the class is loaded and can be accessed without creating an object. An instance member belongs to a particular object and gets its own copy per instance. Static methods cannot access instance state directly because there is no `this`.
9. Can you override a static method? Fresher
No. Static methods are resolved at compile time based on the reference type, not at runtime based on the object — this is called method hiding, not overriding. If a subclass declares a static method with the same signature, calling it through a parent reference invokes the parent's version.
10. What is the difference between pass-by-value and pass-by-reference in Java? Fresher
Java is always pass-by-value. For primitives the value itself is copied. For objects the reference is copied, so the method can mutate the object the reference points to, but reassigning the parameter inside the method does not affect the caller's variable. That distinction is the point of the question.
11. What is the difference between a class and an interface after Java 8? 2–5 yrs
An interface can now have default and static methods with bodies, which narrowed the gap. The remaining differences: a class can hold instance state, an interface's fields are implicitly public static final; a class supports single inheritance, a class can implement many interfaces; and interfaces cannot have constructors. Use an abstract class for shared state, an interface for capability.
12. What is the difference between a checked and an unchecked cast? 2–5 yrs
A checked (safe) cast is one the compiler can verify, such as widening a subclass reference to a superclass. A downcast from a superclass to a subclass is unchecked at compile time and throws ClassCastException at runtime if wrong — which is why you guard it with instanceof, or use pattern matching for instanceof in modern Java.
OOP Concepts
13. What are the four pillars of OOP in Java? Fresher
Encapsulation (bundling data with the methods that operate on it and hiding internal state behind access modifiers), Inheritance (a class deriving fields and behavior from a parent with extends), Polymorphism (one interface taking many forms via overriding and overloading), and Abstraction (exposing essential behavior while hiding implementation through abstract classes and interfaces).
14. What is the difference between method overloading and overriding? Fresher
Overloading means multiple methods in the same class share a name but differ in parameter list; it is resolved at compile time and is a form of compile-time polymorphism. Overriding means a subclass provides its own implementation of a method inherited from a parent with the same signature; it is resolved at runtime and is runtime polymorphism. Overriding uses the @Override annotation and follows rules on access level and return type.
15. What is the difference between an interface and an abstract class? Fresher
An abstract class can have both abstract and concrete methods, instance fields, and constructors, and a class can extend only one of them. An interface defines a contract and (before Java 8) only abstract methods; since Java 8 it can also have default and static methods, but its variables are implicitly public static final and a class can implement many interfaces. Use an abstract class for a shared base with common state, and an interface to define capabilities.
16. Why does Java not support multiple inheritance of classes? Fresher
To avoid the diamond problem — if two parents provide the same method, the compiler cannot decide which to inherit. Java allows multiple interface implementation instead, and since Java 8 when two interfaces provide conflicting default methods the compiler forces the implementing class to override and resolve it explicitly.
17. What are access modifiers in Java? Fresher
private (same class only), default or package-private (same package), protected (same package plus subclasses anywhere), and public (everywhere). Encapsulation in practice means keeping fields private and exposing behaviour through methods rather than exposing state directly.
18. What is a constructor, and can it be overloaded? Fresher
A constructor initialises a new object; it has the same name as the class and no return type. Yes, constructors can be overloaded by parameter list, and one can call another with this(...). If you declare no constructor, Java supplies a no-argument default; if you declare any constructor, the default disappears.
19. What is the difference between this and super? Fresher
this refers to the current object and is used to disambiguate a field from a parameter, or to call another constructor in the same class via this(...). super refers to the parent, used to call an overridden parent method or a parent constructor via super(...). A call to this(...) or super(...) must be the first statement in a constructor.
20. What is the contract between equals() and hashCode()? 2–5 yrs
If two objects are equal by equals(), they must return the same hashCode(). The reverse is not required — unequal objects may share a hash code, which is a collision. Breaking this contract means an object put into a HashMap or HashSet can become unfindable, because lookup goes to the wrong bucket. Always override both together.
21. What is composition, and when should you prefer it to inheritance? 2–5 yrs
Composition means a class holds a reference to another and delegates to it, rather than extending it. Prefer it when the relationship is "has-a" rather than "is-a", when you only want part of the parent's behaviour, or when the parent is not designed for extension. It avoids fragile base-class problems and keeps the hierarchy shallow.
22. What is the SOLID principle set? 2–5 yrs
Single responsibility (a class has one reason to change), Open/closed (open for extension, closed for modification), Liskov substitution (a subtype must be usable wherever its supertype is), Interface segregation (many small interfaces beat one large one), and Dependency inversion (depend on abstractions, not concretions). Interviewers usually follow up asking for a real example of one you have applied.
23. What is an immutable class and how do you write one? 2–5 yrs
An immutable object cannot change after construction. Make the class final so it cannot be subclassed, make all fields private final, set them only in the constructor, provide no setters, and defensively copy any mutable field on the way in and on the way out. String and the java.time types are the canonical examples; immutability makes objects inherently thread-safe.
24. What is the difference between shallow copy and deep copy? 2–5 yrs
A shallow copy duplicates the object but shares references to its nested objects, so mutating a nested object is visible through both copies. A deep copy recursively duplicates the nested objects as well, producing a fully independent graph. Object.clone() gives a shallow copy by default.
25. What is the Liskov substitution principle, with a violation example? Senior
Any place that works with a base type must work with a subtype without knowing it. The classic violation is Square extends Rectangle: code that sets width and height independently and asserts area breaks, because Square couples them. The subtype technically compiles but weakens the parent's contract, which is what LSP forbids.
26. What design patterns come up most in Java interviews? Senior
Singleton (one instance, usually via enum or a static holder), Factory and Abstract Factory (creation behind an interface), Builder (readable construction of objects with many optional fields), Strategy (swap an algorithm at runtime), Observer (publish/subscribe), and Decorator (wrap to add behaviour — the java.io streams are built on it). Be ready to name where you have actually used one.
Strings
27. Why are String objects immutable in Java? Fresher
Once created, a String's value cannot be changed; any modifying operation returns a new String. Immutability enables safe sharing in the String pool, makes strings safe to use as HashMap keys (their hash code never changes), improves security for things like file paths and credentials, and makes them inherently thread-safe. For heavy modification, use StringBuilder or StringBuffer instead.
28. What is the String pool? Fresher
The String pool is a special area of heap memory where the JVM stores string literals to save memory. When you create a string with a literal, the JVM reuses an existing pooled instance if one matches, so two identical literals share the same reference. Strings created with new always produce a separate object on the heap, though you can add them to the pool with intern().
29. What is the difference between String, StringBuilder, and StringBuffer? Fresher
String is immutable, so every modification creates a new object. StringBuilder is mutable and not synchronised, making it the fastest choice for single-threaded string building. StringBuffer is mutable and synchronised, so it is thread-safe but slower. Use StringBuilder unless you genuinely share the buffer across threads.
30. How do you compare two strings in Java? Fresher
Use equals() for content comparison and equalsIgnoreCase() when case does not matter. Use compareTo() when you need ordering — it returns a negative number, zero, or a positive number. Do not use == for strings; it compares references and only appears to work when both happen to be pooled literals, which is why it is such a common bug.
31. What does String.intern() do? 2–5 yrs
It returns the canonical instance of the string from the pool, adding it if absent. It lets you take a runtime-constructed string and get back the shared pooled reference so == comparisons succeed. It is rarely worth it in modern code — the memory saving is small and the pool lookup has a cost.
32. Why is String a popular choice for HashMap keys? 2–5 yrs
Because it is immutable, its hash code cannot change after insertion, so an entry can never become unreachable in its bucket. String also caches its hash code after first computation, making repeated lookups cheap, and it has a well-distributed hashCode implementation.
33. What happens when you concatenate strings in a loop? 2–5 yrs
Each += creates a new String and copies the old contents, giving O(n²) behaviour for n concatenations. The compiler optimises simple concatenation into StringBuilder calls, but not across loop iterations — inside a loop it constructs a new builder each pass. Build with an explicit StringBuilder outside the loop instead.
34. What is compact strings, introduced in Java 9? Senior
Before Java 9, String stored a char[] using two bytes per character regardless of content. Compact strings store a byte[] plus a coder flag, using one byte per character for Latin-1 content and falling back to UTF-16 only when needed. For typical applications this measurably reduces heap usage, since strings are usually the largest category of live objects.
Collections
35. What is the difference between List, Set, and Map? Fresher
A List is an ordered collection that allows duplicate elements and indexed access, with implementations like ArrayList and LinkedList. A Set is a collection that does not allow duplicates, with implementations like HashSet (unordered) and TreeSet (sorted). A Map stores key-value pairs with unique keys, with implementations like HashMap, LinkedHashMap, and TreeMap; Map is not part of the Collection interface hierarchy.
36. What is the difference between ArrayList and LinkedList? Fresher
ArrayList is backed by a dynamic array, giving fast O(1) random access by index but slower insertions and deletions in the middle because elements must shift. LinkedList is a doubly linked list with fast O(1) insertions and deletions at the ends but slow O(n) random access. Use ArrayList for frequent reads and LinkedList when you do a lot of add/remove at the boundaries.
37. How does a HashMap work internally? Fresher
A HashMap stores key-value pairs in an array of buckets, choosing a bucket from the key's hashCode(). When two keys hash to the same bucket (a collision), entries are chained in a linked list, which converts to a balanced tree once a bucket exceeds a threshold (8 in Java 8+) for O(log n) lookups. Equality of keys is resolved with equals(), and the map resizes and rehashes when it passes its load factor (default 0.75).
38. What is the difference between HashMap and Hashtable? Fresher
HashMap is unsynchronised, allows one null key and multiple null values, and is the modern choice. Hashtable is synchronised on every method, allows no nulls, and is a legacy class from Java 1.0. If you need a thread-safe map, use ConcurrentHashMap rather than Hashtable — it is far more concurrent.
39. What is the difference between HashSet and TreeSet? Fresher
HashSet is backed by a HashMap, gives O(1) add/contains, and has no ordering. TreeSet is backed by a red-black tree, gives O(log n) operations, and keeps elements sorted by natural order or a supplied Comparator. Use TreeSet only when you actually need ordering or range queries.
40. What is the difference between Comparable and Comparator? Fresher
Comparable is implemented by the class itself and defines its single natural ordering through compareTo(). Comparator is a separate object defining an alternative ordering through compare(), so you can have many of them and sort the same type different ways without modifying it. Use Comparable for the one obvious order, Comparator for everything else.
41. What is the difference between Iterator and ListIterator? Fresher
Iterator traverses forward only and works on any Collection, supporting remove(). ListIterator works only on Lists, traverses both directions, and additionally supports add(), set(), and index queries. Both are the safe way to remove during iteration.
42. What is a fail-fast iterator, and how does it differ from fail-safe? 2–5 yrs
A fail-fast iterator throws ConcurrentModificationException if the collection is structurally modified during iteration, detected via a modCount field — this is how ArrayList and HashMap behave. A fail-safe iterator works on a copy or a snapshot and does not throw, as in CopyOnWriteArrayList and ConcurrentHashMap, at the cost of possibly not seeing recent changes.
43. How do you safely remove elements while iterating a collection? 2–5 yrs
Use the iterator's own remove() method, or Collection.removeIf() with a predicate, which is clearer and usually faster. Removing directly from the collection inside a for-each loop triggers ConcurrentModificationException, because the for-each is an iterator underneath and the modification count no longer matches.
44. What is the load factor in a HashMap? 2–5 yrs
The load factor is the fill ratio at which the map resizes — default 0.75. When size exceeds capacity × load factor, the table doubles and every entry is rehashed. 0.75 is a deliberate trade-off: lower means fewer collisions but more wasted space and more frequent resizes; higher means denser buckets and slower lookups.
45. What is the difference between HashMap and LinkedHashMap? 2–5 yrs
LinkedHashMap extends HashMap and additionally maintains a doubly linked list across entries, so iteration follows insertion order (or access order if constructed that way). That ordering costs a little memory and insertion time. The access-order mode makes it a natural base for an LRU cache when you override removeEldestEntry().
46. How would you build an LRU cache in Java? 2–5 yrs
The simplest correct answer is LinkedHashMap constructed with accessOrder=true, overriding removeEldestEntry() to return true past your capacity. If asked to build it from scratch, use a HashMap for O(1) lookup plus a doubly linked list for O(1) reordering — the map holds key to node, and every access moves that node to the head.
47. What is ConcurrentHashMap and how does it achieve thread safety? 2–5 yrs
It is a thread-safe map that allows concurrent reads and a high degree of concurrent writes. Java 7 used lock striping across segments; Java 8 replaced that with per-bucket synchronisation using CAS for the common case and synchronising only on the head node of a contended bucket. Reads are generally lock-free.
48. What is the difference between Collections.synchronizedMap() and ConcurrentHashMap? 2–5 yrs
synchronizedMap wraps a map and guards every method with a single lock, so only one thread touches it at a time and compound operations still need external synchronisation. ConcurrentHashMap locks at bucket granularity and provides atomic compound operations like putIfAbsent, compute, and merge. It scales far better under contention.
49. Why should you avoid mutable objects as HashMap keys? Senior
The hash code is computed at insertion time to choose a bucket. If you mutate a field that participates in hashCode(), the object now hashes to a different bucket, so get() looks in the wrong place and the entry becomes unreachable even though it is still in the map. This is a classic source of silent data loss.
50. What is CopyOnWriteArrayList and when is it appropriate? Senior
It is a thread-safe List that copies the entire backing array on every mutation, so iterators operate on an immutable snapshot and never throw ConcurrentModificationException. Writes are O(n) and allocate, so it only makes sense when reads vastly outnumber writes — a listener or subscriber registry is the canonical case.
Exception Handling
51. What is the difference between checked and unchecked exceptions? Fresher
Checked exceptions (like IOException and SQLException) are checked at compile time and must be either caught or declared with throws. Unchecked exceptions extend RuntimeException (like NullPointerException and ArrayIndexOutOfBoundsException) and represent programming errors, so the compiler does not force you to handle them. Errors, like OutOfMemoryError, are serious conditions you are generally not expected to catch.
52. What is the difference between throw and throws? Fresher
throw is a statement that actually raises an exception instance at a point in the code. throws is a clause in a method signature declaring which checked exceptions the method may propagate to its caller. One is an action, the other is a declaration.
53. What is the difference between final, finally, and a finally block that returns? Fresher
A finally block always runs, even when the try or catch returns or throws. If finally itself returns a value, it silently discards whatever the try block was returning — and swallows any in-flight exception. That is why returning from finally is considered a bug rather than a technique.
54. What is try-with-resources? Fresher
A try statement that declares resources implementing AutoCloseable; the JVM closes them automatically in reverse order when the block exits, whether normally or by exception. It replaces the error-prone finally-with-null-check pattern and correctly handles exceptions thrown by close(), attaching them as suppressed exceptions rather than losing the original.
55. What is exception chaining? 2–5 yrs
Wrapping a caught low-level exception inside a higher-level one, passing the original as the cause — new ServiceException("could not load user", ex). It lets you raise an abstraction-appropriate exception without discarding the underlying stack trace, which is what makes production failures diagnosable.
56. When should you create a custom exception? 2–5 yrs
When callers need to react differently to this failure than to others, and no existing exception expresses it. Extend RuntimeException for programming or unrecoverable errors and Exception for conditions a caller can meaningfully recover from. A custom exception that nobody catches specifically is just noise.
57. What is a multi-catch block? 2–5 yrs
Since Java 7 you can catch several exception types in one clause with catch (IOException | SQLException e), avoiding duplicated handling code. The parameter is implicitly final, and the types must not be in a subclass relationship with each other.
58. Why is catching Exception or Throwable broadly a problem? Senior
Catching Exception swallows unrelated failures you did not anticipate, including bugs that should have surfaced. Catching Throwable is worse — it captures Errors such as OutOfMemoryError and StackOverflowError, where continuing execution is meaningless and often makes diagnosis harder. Catch the narrowest type you can actually handle.
59. What happens if an exception is thrown inside a finally block? Senior
It replaces any exception currently propagating from the try or catch, and the original is lost — a well-known source of vanished stack traces. try-with-resources solves this properly by suppressing rather than replacing, exposing the original via getSuppressed().
Multithreading & Concurrency
60. How do you create a thread in Java? Fresher
You can extend the Thread class and override its run() method, or implement the Runnable interface and pass it to a Thread; implementing Runnable is preferred because it keeps your class free to extend something else. In modern code you typically submit Runnable or Callable tasks to an ExecutorService from java.util.concurrent rather than managing threads by hand. You start a thread with start(), which invokes run() on a new thread of execution.
61. What is the difference between start() and run()? Fresher
start() registers a new thread with the scheduler and invokes run() on it. Calling run() directly just executes the method on the current thread, with no concurrency at all — a classic interview trap. Calling start() twice on the same Thread throws IllegalThreadStateException.
62. What is the difference between Runnable and Callable? Fresher
Runnable.run() returns nothing and cannot throw checked exceptions. Callable.call() returns a value and may throw checked exceptions, and submitting one to an ExecutorService gives you a Future to retrieve the result or the exception. Use Callable whenever the task produces something.
63. What are the thread lifecycle states? Fresher
NEW (created, not started), RUNNABLE (eligible to run or running), BLOCKED (waiting for a monitor lock), WAITING (waiting indefinitely for another thread's action), TIMED_WAITING (waiting with a timeout, as with sleep or join with a duration), and TERMINATED (finished). Note RUNNABLE covers both ready and actually executing — Java does not distinguish them.
64. What is the difference between synchronized and volatile? Fresher
synchronized provides mutual exclusion so only one thread enters a block or method at a time, guaranteeing both atomicity and visibility of changes. volatile only guarantees visibility — every read sees the latest write directly from main memory — but it does not make compound operations like increment atomic. Use volatile for simple flags and synchronized (or locks and atomic classes) when you need atomic updates.
65. What is the difference between sleep() and wait()? 2–5 yrs
sleep() is a static Thread method that pauses the current thread for a duration and does not release any lock it holds. wait() is an Object method that must be called while holding that object's monitor, releases the lock, and parks the thread until notify()/notifyAll() or a timeout. Using sleep() while holding a lock is a common cause of stalls.
66. What is a deadlock and how do you prevent it? 2–5 yrs
A deadlock is two or more threads each holding a lock the other needs, so none can proceed. Prevent it by acquiring locks in a consistent global order, using timed acquisition with tryLock() so a thread can back off, holding locks for the shortest possible time, and preferring higher-level concurrency utilities over hand-rolled locking.
67. What is the difference between deadlock, livelock, and starvation? 2–5 yrs
In a deadlock, threads are blocked forever waiting on each other. In a livelock, threads keep running and changing state in response to each other but make no progress — two people repeatedly stepping aside in a corridor. In starvation, a thread is runnable but never scheduled because other threads monopolise the resource, often due to priority or unfair locking.
68. What is an ExecutorService and why prefer it to raw threads? 2–5 yrs
It is a managed thread pool that decouples task submission from thread lifecycle. It reuses threads rather than paying creation cost per task, bounds concurrency so you do not exhaust memory under load, provides Futures for results, and gives you orderly shutdown. Creating a thread per request is the failure mode it exists to prevent.
69. What is the difference between submit() and execute()? 2–5 yrs
execute() takes a Runnable and returns nothing, so an uncaught exception surfaces through the thread's uncaught-exception handler. submit() accepts a Runnable or Callable and returns a Future, and any exception is captured inside that Future — meaning it is silently swallowed unless you call get(). That silent swallowing is a very common production bug.
70. What are atomic classes like AtomicInteger for? 2–5 yrs
They provide lock-free thread-safe operations on a single variable using compare-and-swap instructions. incrementAndGet() is atomic where count++ on a volatile int is not, because ++ is a read-modify-write. Under low to moderate contention they are considerably faster than synchronisation.
71. What is ThreadLocal and when is it used? 2–5 yrs
ThreadLocal gives each thread its own independently initialised copy of a variable, commonly used for per-request context, user identity, or non-thread-safe objects like SimpleDateFormat. The critical caveat is pooled threads: a value left behind leaks into the next task and can pin objects in memory, so always remove() in a finally block.
72. What is the Java Memory Model, in practical terms? Senior
It defines when a write by one thread becomes visible to another, via the happens-before relationship. Practically: releasing a lock happens-before acquiring it, a volatile write happens-before a subsequent read of that variable, and Thread.start() happens-before anything the new thread does. Without such an edge, the JVM and CPU are free to reorder and cache, so another thread may never see your write.
73. What is the difference between synchronized and ReentrantLock? Senior
synchronized is a language construct with automatic release and no ability to time out. ReentrantLock is an explicit object supporting tryLock() with a timeout, interruptible acquisition, a fairness policy, and multiple Condition objects for finer-grained waiting. The cost is that you must release it in a finally block — forgetting is a permanent lock leak.
74. What are virtual threads and what problem do they solve? Senior
Virtual threads, delivered by Project Loom, are lightweight threads scheduled by the JVM rather than the OS, so you can run millions of them. They make blocking I/O cheap again: a virtual thread parked on a blocking call unmounts from its carrier thread instead of holding an OS thread. That lets thread-per-request code scale without adopting reactive programming, though synchronized blocks can still pin a carrier thread.
Memory & Garbage Collection
75. How does garbage collection work in Java? Fresher
The JVM automatically reclaims memory from objects that are no longer reachable from any live reference, so you do not free memory manually. The heap is divided into generations — a young generation (Eden and survivor spaces) for new objects and an old generation for long-lived ones — based on the observation that most objects die young. Collectors like G1 run minor and major cycles; you can suggest collection with System.gc() but cannot force it.
76. What is the difference between stack and heap memory? Fresher
The stack holds method frames, local variables, and references, is per-thread, and is freed automatically when a method returns. The heap holds all objects, is shared across threads, and is managed by the garbage collector. A deep recursion exhausts the stack (StackOverflowError); too many live objects exhaust the heap (OutOfMemoryError).
77. What makes an object eligible for garbage collection? 2–5 yrs
It becomes unreachable from any GC root — meaning no chain of references leads to it from a live thread's stack, a static field, or a JNI reference. Setting a reference to null helps only if that was the last reference. Note that islands of mutually referencing objects are still collectable, because reachability, not reference counting, is the criterion.
78. What is a memory leak in Java, given garbage collection? 2–5 yrs
A leak here means unintentionally retained reachability — objects you no longer need but which are still referenced, so the collector cannot reclaim them. Classic causes: growing static collections, unremoved listeners, ThreadLocals on pooled threads, and unclosed resources. The heap fills with live-but-useless objects.
79. What are strong, soft, weak, and phantom references? 2–5 yrs
A strong reference is the ordinary kind and prevents collection. A SoftReference is cleared only when memory is tight, which suits caches. A WeakReference is cleared at the next collection once no strong references remain — this is how WeakHashMap keys work. A PhantomReference is never dereferenceable and exists to schedule cleanup after collection, replacing finalize().
80. What is the difference between a minor, major, and full GC? Senior
A minor GC collects the young generation only and is fast, since most young objects are dead. A major GC collects the old generation. A full GC collects the whole heap including metaspace and typically involves a longer stop-the-world pause. Frequent full GCs are usually a symptom of either a leak or an undersized heap.
81. What garbage collectors does modern Java offer, and how do you choose? Senior
Serial for tiny heaps and single-core environments; Parallel for throughput-oriented batch work; G1 as the balanced default, region-based with a pause-time target; ZGC and Shenandoah for very large heaps with sub-millisecond pauses. Choose on the axis you care about — throughput versus latency — and measure rather than assume.
82. What is metaspace, and how does it differ from PermGen? Senior
Metaspace replaced PermGen in Java 8 and holds class metadata. Unlike PermGen it lives in native memory rather than the heap and grows dynamically, so the old java.lang.OutOfMemoryError: PermGen space largely disappeared. It can still be exhausted by classloader leaks, which is what repeated redeploys in an application server tend to produce.
Java 8 and Later
83. What is a lambda expression? Fresher
A concise way to express an instance of a functional interface — an interface with exactly one abstract method. Instead of an anonymous class you write parameters, an arrow, and a body: (a, b) -> a + b. Lambdas capture effectively final local variables and do not introduce a new scope for this, unlike anonymous classes.
84. What is a functional interface? Fresher
An interface with a single abstract method, which makes it a valid lambda target. @FunctionalInterface documents that intent and makes the compiler enforce it. The standard set lives in java.util.function: Function, Predicate, Consumer, Supplier, and the primitive-specialised variants.
85. What is the Stream API? Fresher
A declarative pipeline for processing sequences of elements: a source, zero or more intermediate operations like filter and map, and a terminal operation like collect or forEach. Intermediate operations are lazy — nothing runs until the terminal operation. Streams do not store data and do not modify their source.
86. What is the difference between map() and flatMap()? Fresher
map() transforms each element one-to-one, so a Stream<List<String>> mapped stays a stream of lists. flatMap() transforms each element into a stream and concatenates the results, flattening one level — turning Stream<List<String>> into Stream<String>. Reach for flatMap whenever mapping would give you a nested structure.
87. What is Optional and what problem does it solve? Fresher
Optional is a container that may or may not hold a non-null value, used to make absence explicit in a return type rather than returning null and hoping the caller checks. Use map, filter, orElse, and orElseThrow to work with it. It is designed for return values — using it for fields or parameters is generally considered misuse.
88. What is the difference between intermediate and terminal stream operations? 2–5 yrs
Intermediate operations (filter, map, sorted, distinct) return a new stream and are lazy — they build up a pipeline without processing anything. Terminal operations (collect, reduce, forEach, count, anyMatch) trigger execution and consume the stream. A stream cannot be reused after a terminal operation.
89. What are default and static methods in interfaces? 2–5 yrs
A default method has a body and is inherited by implementors, which is how Java added methods like Collection.stream() without breaking every existing implementation. A static method on an interface belongs to the interface itself and is not inherited. If two interfaces supply conflicting defaults, the implementing class must override to resolve it.
90. What is method reference syntax? 2–5 yrs
Shorthand for a lambda that only calls an existing method: String::toUpperCase, System.out::println, ArrayList::new. Four forms exist — static method, instance method of a particular object, instance method of an arbitrary object of a type, and constructor. It is purely readability; the semantics match the equivalent lambda.
91. What does Collectors.groupingBy() do? 2–5 yrs
It is a terminal collector that partitions stream elements into a Map keyed by a classifier function, with lists of matching elements as values by default. A second collector argument lets you reduce each group — counting(), summingInt(), or mapping() — which is how you express most reporting queries in one pass.
92. What is the difference between findFirst() and findAny()? 2–5 yrs
findFirst() returns the first element in encounter order, which matters on an ordered stream. findAny() is free to return any element, letting a parallel stream avoid the coordination cost of determining what "first" means. On a sequential stream they usually behave identically.
93. When are parallel streams actually worth using? Senior
Rarely, and only after measuring. They pay off when the dataset is large, the per-element work is CPU-bound and independent, and the source splits evenly — an array or ArrayList rather than a LinkedList. They hurt when tasks are short, when the operation blocks on I/O, or when the workload is already parallel, because they share the common ForkJoinPool with everything else in the JVM.
94. What is CompletableFuture? Senior
An implementation of Future supporting non-blocking composition: thenApply, thenCompose, thenCombine, allOf, and exceptionally let you build asynchronous pipelines without blocking on get(). It is how you fan out concurrent calls and join their results. Watch which executor each stage runs on — the default is the common ForkJoinPool, which is a poor place for blocking work.
95. What are records, and when should you use one? Senior
A record is a concise, immutable data carrier — record Point(int x, int y) generates the constructor, accessors, equals, hashCode, and toString. Use them for DTOs, value objects, and query results. They cannot extend a class and their fields are final, which is the point: they model data, not behaviour.
96. What are sealed classes for? Senior
A sealed class or interface restricts which types may extend or implement it, declared with permits. That makes a hierarchy closed and exhaustively known to the compiler, so a switch over its subtypes needs no default branch. Combined with records and pattern matching, it gives Java algebraic data types and safe exhaustive handling.
JVM Internals & Performance
97. What does the JVM classloader do? 2–5 yrs
It loads class bytecode into memory on first use, following delegation: a loader asks its parent before trying itself, so bootstrap loads core JDK classes, then platform, then application. This parent-first model prevents application code from replacing java.lang.String. Custom loaders enable plugin isolation and hot redeploy — and are a frequent source of metaspace leaks.
98. What is JIT compilation? 2–5 yrs
The JVM starts by interpreting bytecode, profiles which methods run hot, then compiles those to native code at runtime — with tiered compilation moving through C1 to C2. Because it optimises against observed behaviour, it can inline aggressively and speculate on types in ways an ahead-of-time compiler cannot. It is also why JVM benchmarks need a warm-up phase to mean anything.
99. What is the difference between an OutOfMemoryError and a StackOverflowError? 2–5 yrs
OutOfMemoryError means the heap (or metaspace, or direct memory) cannot satisfy an allocation — usually a leak, an undersized heap, or genuinely too much live data. StackOverflowError means a single thread's stack is exhausted, almost always from unbounded or overly deep recursion. Both are Errors, not Exceptions, and should not be caught routinely.
100. How would you diagnose a memory leak in a running Java application? Senior
Confirm the shape first — is the heap after full GC trending upward over time? Then take a heap dump (jmap or an OnOutOfMemoryError flag) and open it in a tool like Eclipse MAT, which reports dominator trees and leak suspects. Look for the largest retained sets and walk the path back to the GC root holding them. Static collections, caches without eviction, and ThreadLocals on pooled threads are the usual answers.
101. How would you investigate high CPU usage in a Java process? Senior
Find the hot OS threads (top -H), convert their IDs to hex, take several thread dumps with jstack, and match the IDs to see what those threads are actually doing. Repeat sampling so you distinguish a genuinely hot method from a snapshot artefact. Common causes: an infinite or spinning loop, excessive GC, or regex and serialisation hot spots. A profiler such as async-profiler gives a cleaner flame graph.
102. What is escape analysis? Senior
A JIT optimisation that determines whether an object can be referenced outside the method creating it. If it cannot escape, the JVM may allocate it on the stack instead of the heap, eliminate the allocation entirely by scalar replacement, or remove redundant locks. This is why writing obviously allocation-heavy but local code is often cheaper than it looks.
103. What is the difference between -Xms and -Xmx? Senior
-Xms sets the initial heap size and -Xmx the maximum. Setting them equal is common in servers because it avoids the cost and pause variability of the heap resizing under load, and it makes memory behaviour predictable. Sizing the max too close to container limits is a frequent cause of the container OOM-killing the process before the JVM ever reports an OutOfMemoryError.
104. How do you make a class thread-safe? Senior
In rough order of preference: make it immutable so there is no shared mutable state at all; confine state to a single thread; use existing thread-safe types from java.util.concurrent; or guard mutable state with synchronisation, documenting exactly which lock protects which field. The last option is the most error-prone and the one interviewers probe hardest.
105. What is the double-checked locking pattern, and why was it historically broken? Senior
It is lazy singleton initialisation that checks a field, synchronises only if null, then checks again. Before Java 5 it was broken because the instruction to publish the reference could be reordered ahead of the constructor finishing, letting another thread see a partially built object. Declaring the field volatile fixes it under the modern memory model — though a static holder class or an enum is simpler and preferred.
Get these answered live in your real interview
NostrobeAI is a real-time AI interview copilot — it hears the question and drafts a strong answer on your screen, invisible on Zoom, Meet, and Teams. One-time pricing, no subscription.
Try NostrobeAI free