36 practice questions with answers for Java interviews in Lucknow.
Java jobs in Lucknow
Lucknow's tech job market is smaller but growing, led by IT-services delivery centres, government-tech projects and start-ups. Many Lucknow candidates target Noida and Gurgaon roles or remote jobs, so interviews follow the NCR pattern.
Below are 36 questions that match the mix of service, product and domain employers hiring java developers in Lucknow.
Solved for LucknowStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
✓ 3 questions free • Unlock the rest in seconds
01
What is the difference between an abstract class and an interface in modern Java?
An abstract class can have state (instance fields), constructors and any access modifier, and a class can extend only one. An interface has no instance state but, since Java 8, can have default and static methods, and since Java 9 private methods; a class can implement many. Use an interface for a capability contract and an abstract class to share code and state among closely related classes.
Access order plus removeEldestEntry gives LRU in a few lines.
class LruCache<K, V> extends LinkedHashMap<K, V> {
private final int capacity;
LruCache(int capacity) {
super(16, 0.75f, true);
this.capacity = capacity;
}
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> e) {
return size() > capacity;
}
}
get and put are O(1).
03
When would you choose ArrayDeque over Stack and LinkedList?
Stack is a legacy synchronized class built on Vector, so it is slow and exposes index methods that break stack rules. LinkedList allocates a node per element. ArrayDeque is a resizable circular array with no per-element allocation, so push, pop, offer and poll are fast amortised O(1). Use ArrayDeque for both stacks and queues in single-threaded code; it does not accept null.
04
A query is fast in development but takes 8 seconds in production. How do you investigate?
Production has more data, so check the execution plan with EXPLAIN ANALYZE on production-like data. Look for full table scans, missing indexes on filter or join columns, functions on indexed columns and poor statistics. Check if Hibernate generates the SQL you expect. Add a suitable composite index, rewrite the query or paginate, and verify the plan improves before release.
05
Describe a time you improved the design of existing code.
Situation: our notification module used a 400 line class with switch cases for email, SMS and WhatsApp. Task: add push notifications without breaking anything. Action: I wrote tests for current behaviour, extracted a Notifier interface with one class per channel and used Spring to inject them by type. Result: push was added in one new class, bugs in that module dropped and new channels now take hours, not days.
Transient: a new object not yet linked to a persistence context. Managed (persistent): attached to the context, so changes are tracked and flushed automatically through dirty checking. Detached: was managed but the context closed or it was evicted; changes are not tracked until merge(). Removed: scheduled for deletion on flush. persist, merge, detach and remove move entities between these states.
The JVM first interprets bytecode, then profiles which methods run often. The Just In Time compiler converts these hot methods into optimised native code at runtime. HotSpot uses tiered compilation: C1 compiles quickly with light optimisation and C2 applies aggressive optimisations like inlining and escape analysis. This is why Java apps get faster after a warm-up period.
08
Write a custom unchecked exception and a Spring handler that returns HTTP 404.
Define the exception, then map it centrally.
public class NotFoundException extends RuntimeException {
public NotFoundException(String msg) { super(msg); }
}
@RestControllerAdvice
public class ApiErrors {
@ExceptionHandler(NotFoundException.class)
public ProblemDetail notFound(NotFoundException e) {
return ProblemDetail.forStatusAndDetail(
HttpStatus.NOT_FOUND, e.getMessage());
}
}
09
Write a Spring Data JPA repository method that fetches orders with items to avoid N+1.
Use JOIN FETCH or an entity graph.
public interface OrderRepository extends JpaRepository<Order, Long> {
@Query("select distinct o from Order o join fetch o.items where o.customerId = :cid")
List<Order> findWithItems(@Param("cid") Long customerId);
@EntityGraph(attributePaths = "items")
List<Order> findByStatus(String status);
}
Both load orders and items in one query.
At startup Spring Boot reads auto-configuration classes listed in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. Each class uses conditions like @ConditionalOnClass, @ConditionalOnMissingBean and @ConditionalOnProperty, so it creates beans only when the library is on the classpath and you have not defined your own. Run with --debug to see the condition report showing what was applied and why.
11
How do you create a custom exception and when should you?
Extend RuntimeException for unchecked or Exception for checked, and provide constructors that accept a message and a cause so the root stack trace is kept. Create one when a domain error needs specific handling, such as InsufficientBalanceException, which a Spring @ControllerAdvice can map to an HTTP 422 response. Do not create exceptions for normal control flow.
12
Should a service layer throw checked or unchecked exceptions? Defend your choice.
I prefer unchecked domain exceptions in the service layer. Checked exceptions force every caller to catch or declare them, leak low level details through layers and do not work well with lambdas. Unchecked exceptions with clear names, handled centrally by a controller advice, keep code clean. Spring follows the same idea by translating SQLException into its unchecked DataAccessException family.
Autoboxing is automatic conversion between a primitive and its wrapper, such as int to Integer, and unboxing is the reverse. A common pitfall is a NullPointerException when unboxing a null Integer. Another is comparing Integer objects with ==, which works only for cached values from -128 to 127. Boxing inside tight loops also creates extra garbage and slows code.
14
Write a JDBC method to fetch a user by email safely.
Records, final in Java 16, are concise classes for immutable data. record Point(int x, int y) {} generates private final fields, a canonical constructor, accessors, equals(), hashCode() and toString(). You can add validation in a compact constructor and add methods. Use them for DTOs, API responses and map keys. They cannot extend another class and are not suited to JPA entities, which need mutability.
Situation: three freshers joined my Spring Boot team at once. Task: make them productive quickly. Action: I created a starter task list, paired with each on their first story, gave detailed but kind code reviews and held a weekly session on topics like transactions and testing. Result: all three shipped features independently within a month and one now mentors new joiners.
17
An API calls three independent downstream services one after another and takes 900 ms. How would you speed it up?
Since the calls are independent, run them in parallel with CompletableFuture.supplyAsync on a dedicated executor or with virtual threads, then join with allOf. Total latency becomes roughly the slowest call, about 300 ms. Add a timeout per call with orTimeout and a fallback for failures so one slow service does not block the whole response. Structured concurrency is another option in newer Java.
Strings are immutable so they can be safely shared from the string pool, used as HashMap keys with a cached hash code, passed between threads without locking and trusted in security checks such as file paths and class names. Any change, like concat or replace, creates a new String. For heavy modification use StringBuilder, which changes its internal buffer in place.
19
What is the difference between synchronized and ReentrantLock?
synchronized is a built-in keyword that locks a monitor and releases it automatically at block exit. ReentrantLock is an explicit lock that adds tryLock with timeout, interruptible locking, fairness options and multiple Condition objects, but you must unlock in a finally block. Both are reentrant. Prefer synchronized for simple cases and ReentrantLock when you need its extra features.
20
Explain the hierarchy of the Java Collections Framework.
The root interface is Iterable, then Collection, which has List (ordered, allows duplicates: ArrayList, LinkedList), Set (unique: HashSet, LinkedHashSet, TreeSet) and Queue/Deque (PriorityQueue, ArrayDeque). Map is separate and stores key-value pairs: HashMap, LinkedHashMap, TreeMap and ConcurrentHashMap. Java 21 added SequencedCollection and SequencedMap with getFirst() and getLast().
21
Exceptions are being swallowed with empty catch blocks in your codebase. How would you fix this?
Empty catches hide failures and make production issues invisible. I would find them with static analysis like SonarQube, then decide per case: handle the error properly, rethrow wrapped with context, or at least log with the stack trace. I would add a global exception handler for APIs and a team rule in code review and lint config to block new empty catch blocks.
22
Print numbers 1 to 10 alternately from two threads (odd and even).
Use a shared lock with wait and notify.
class Printer {
int n = 1;
synchronized void print(boolean odd) throws InterruptedException {
while (n <= 10) {
if ((n % 2 == 1) == odd) {
System.out.println(Thread.currentThread().getName() + " " + n++);
notifyAll();
} else wait();
}
notifyAll();
}
}
Start one thread with print(true) and another with print(false).
A functional interface has exactly one abstract method, so it can be implemented with a lambda or method reference. It may also have default and static methods. Examples are Runnable, Comparator, and those in java.util.function: Function, Predicate, Consumer, Supplier and BiFunction. The @FunctionalInterface annotation makes the compiler enforce the single abstract method rule.
25
Find the first non-repeating character in a string.
Count in one pass, then scan again in order.
public static char firstUnique(String s) {
int[] cnt = new int[128];
for (char c : s.toCharArray()) cnt[c]++;
for (char c : s.toCharArray()) {
if (cnt[c] == 1) return c;
}
return '_';
}
Two passes, O(n) time and O(1) extra space for ASCII input.
Exception chaining wraps a low level exception in a higher level one while keeping the original as the cause, for example throw new OrderException("save failed", sqlEx). The full stack trace shows both, with Caused by lines. It lets each layer speak its own language without losing the root cause, which is essential when debugging production logs.
27
How do you take a thread dump and a heap dump of a running Java process?
Find the process id with jps or ps, then use jcmd, which is the recommended tool.
jps -l
jcmd <pid> Thread.print > threads.txt
jcmd <pid> GC.heap_dump /tmp/heap.hprof
Older tools jstack and jmap do the same. Take three thread dumps a few seconds apart to spot stuck threads, and analyse heap dumps in Eclipse MAT.
28
What is the difference between HashMap and ConcurrentHashMap?
HashMap is not thread safe; concurrent writes can lose data or corrupt the structure. ConcurrentHashMap supports full concurrency: reads are lock free and writes use CAS or lock a single bin, so threads rarely block each other. It does not allow null keys or values. It also provides atomic compound operations such as computeIfAbsent and merge, which avoid check-then-act races.
29
Your service throws OutOfMemoryError: Java heap space in production. How do you investigate?
First capture evidence: enable -XX:+HeapDumpOnOutOfMemoryError and check GC logs to see if heap grows steadily, which signals a leak, or spikes, which signals a large request. Analyse the heap dump in Eclipse MAT or VisualVM and look at the dominator tree for big retainers like static maps or caches. Fix the leak or bound the cache, then increase -Xmx only if the real workload needs it.
Situation: in college I tried several languages for projects. Task: I wanted one that leads to stable, well paid work. Action: I found Java powers banking, ecommerce and enterprise backends, has strong tooling and a huge job market, so I built two Spring Boot projects and practised DSA in Java. Result: I am confident in the language and keen to keep learning modern features like records and virtual threads.
31
What is the difference between HashMap, LinkedHashMap and TreeMap?
HashMap gives O(1) average operations with no ordering guarantee. LinkedHashMap keeps insertion order, or access order if configured, which helps build an LRU cache. TreeMap keeps keys sorted by natural order or a Comparator with O(log n) operations and supports range methods like floorKey and headMap. HashMap allows one null key; TreeMap does not allow null keys with natural ordering.
Fail-fast iterators, used by ArrayList and HashMap, throw ConcurrentModificationException if the collection is structurally modified during iteration other than through the iterator itself; they check a modCount. Fail-safe or weakly consistent iterators, as in ConcurrentHashMap and CopyOnWriteArrayList, work on a snapshot or tolerate changes and never throw, but may not show the latest updates.
volatile guarantees visibility and ordering: a write to a volatile field is immediately visible to other threads, and it prevents reordering around that access under the Java Memory Model. It does not make compound operations like count++ atomic, because that is a read, modify and write. Use it for flags such as a stop signal, and use AtomicInteger or locks for counters.
34
Implement a producer-consumer using BlockingQueue.
Distributed two-phase commit is fragile, so use the saga pattern. Each service performs a local transaction and publishes an event; failures trigger compensating actions, such as releasing stock when payment fails. Use the transactional outbox pattern so the database change and event publish never diverge, and make consumers idempotent because Kafka may deliver a message more than once.
36
An application gets StackOverflowError in a recursive method. What do you do?
StackOverflowError means the thread stack is full, usually because recursion has no proper base case or the input is very deep. First check the base case and the recursive step with the failing input. If recursion is correct but deep, such as walking a long linked structure, convert it to an iterative solution with an explicit stack. Raising -Xss is only a temporary workaround.
Which companies hire Java professionals in Lucknow?
Companies with large offices in Lucknow include HCLTech. Use their company pages below to practise employer-specific sets.
Are Java interviews in Lucknow different from other cities?
The questions depend more on the company than the city. Lucknow's mix of employers decides the style: Many Lucknow candidates target Noida and Gurgaon roles or remote jobs, so interviews follow the NCR pattern
How do I find Java jobs in Lucknow?
Shortlist companies with Lucknow offices, keep your CV focused on Java projects, apply on company career pages and job portals with the Lucknow filter, and practise the questions on this page before each interview.