Java Interview Preparation — Complete Guide
In this tutorial, you will learn about Java Interview Preparation. We cover key concepts, practical examples, and best practices to help you master this topic.
Mastering the Java Interview
This lesson consolidates everything you have learned across the 69 previous lessons and prepares you for Java technical interviews at all levels. Java interviews typically evaluate four areas: core language fundamentals, object-oriented design, concurrency and performance, and framework/architecture knowledge (especially Spring Boot and microservices).
This lesson is structured as a quick-reference guide with curated questions, code snippets, and key concepts for each topic. Use it alongside your own practice to build confidence for the interview.
flowchart TB
Core[Core Java] --> OOP[OOP & Design]
Core --> Collections[Collections API]
Core --> Exceptions[Exception Handling]
Concurrency[Concurrency] --> JVM[JVM Internals]
Concurrency --> VT[Virtual Threads]
Frameworks[Spring Boot] --> REST[REST APIs]
Frameworks --> Data[Data Access]
Architecture[Architecture] --> Microservices[Microservices]
Architecture --> Design[Design Patterns]
Core Java Fundamentals
Key Concepts
- JVM, JRE, JDK: JVM runs bytecode; JRE = JVM + libraries; JDK = JRE + development tools
- Memory management: Heap (objects), Stack (method frames, primitives), Metaspace (class metadata)
- Garbage collection: Reachability, generational collection, GC types (G1, ZGC, Shenandoah)
- String pool: Strings interned in the heap;
new String()creates a heap object even if pool exists - Immutability:
finalfields, no setters, defensive copying in getters, record types - Pass by value: Java is always pass by value; object references are passed by value
Sample Questions
Q: What is the difference between == and .equals()?
String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");
System.out.println(s1 == s2); // true (same interned string)
System.out.println(s1 == s3); // false (different objects)
System.out.println(s1.equals(s3)); // true (same content)
Q: How does final work in different contexts?
final class Immutable { } // Cannot be extended
final int MAX_SIZE = 100; // Cannot be reassigned
final List<String> list = new ArrayList<>();
list.add("ok"); // Object can be modified
list = new ArrayList<>(); // Compile error: cannot reassign
Q: Explain the difference between abstract class and interface in modern Java.
| Feature | Abstract Class | Interface (Java 8+) |
|---|---|---|
| Constructor | Yes | No |
| Fields | Any fields | public static final constants |
| Methods | Abstract + concrete | Abstract + default + static + private |
| Multiple inheritance | No (single) | Yes (multiple) |
| State | Can hold state | Cannot hold state |
Object-Oriented Design
SOLID Principles
// Single Responsibility: one reason to change
class Invoice { /* data */ }
class InvoicePrinter { /* print logic */ }
class InvoiceRepository { /* persistence */ }
// Open/Closed: open for extension, closed for modification
interface Discount { double apply(double price); }
class PercentageDiscount implements Discount { }
class FixedDiscount implements Discount { }
// Liskov Substitution: subtypes replace base types
void process(Discount discount) { // Works with any Discount }
// Interface Segregation: small, focused interfaces
interface Readable { String read(); }
interface Writable { void write(String data); }
// Dependency Inversion: depend on abstractions
class OrderService {
private final PaymentProcessor processor; // Interface, not concrete class
}
Sample Questions
Q: How would you design a parking lot system?
- Identify entities: ParkingLot, Level, Spot, Vehicle, Ticket, Payment
- Use inheritance: Vehicle (Car extends Vehicle, Motorcycle extends Vehicle)
- Use strategy: SpotAssignmentStrategy (nearest, farthest)
- Use enum: VehicleType, SpotSize, ParkingStatus
- Consider concurrency for entry/exit gates
Q: What is composition over inheritance? Provide an example.
// Inheritance (tight coupling)
class Dog extends Animal { }
// Composition (flexible)
class Dog {
private final AnimalBehavior behavior = new AnimalBehavior();
private final BarkBehavior barkBehavior = new LoudBark();
}
Collections Framework
Hierarchy
Iterable -> Collection -> List (ArrayList, LinkedList)
-> Set (HashSet, LinkedHashSet, TreeSet)
-> Queue (PriorityQueue, ArrayDeque)
Map (HashMap, LinkedHashMap, TreeMap, ConcurrentHashMap)
Key Implementation Details
| Implementation | Underlying Structure | Ordering | Thread-Safe |
|---|---|---|---|
| ArrayList | Resizable array | Insertion order | No |
| LinkedList | Doubly-linked list | Insertion order | No |
| HashSet | HashMap-backed | No ordering | No |
| TreeSet | TreeMap (Red-Black) | Sorted (Comparable/Comparator) | No |
| HashMap | Array of buckets + tree | No ordering | No |
| ConcurrentHashMap | Segmented buckets | No ordering | Yes |
| CopyOnWriteArrayList | Copy-on-write array | Insertion order | Yes |
Sample Questions
Q: How does HashMap handle collisions?
In Java 8+, when the number of collisions in a bucket exceeds TREEIFY_THRESHOLD (8), the linked list transforms into a balanced tree (Red-Black). This improves worst-case performance from O(n) to O(log n). When size drops below UNTREEIFY_THRESHOLD (6), it changes back to a linked list.
Q: What is the difference between fail-fast and fail-safe iterators?
// fail-fast: throws ConcurrentModificationException
List<String> list = new ArrayList<>();
for (String s : list) {
if (s.equals("x")) list.remove(s); // Exception!
}
// fail-safe: works on a copy
CopyOnWriteArrayList<String> cowList = new CopyOnWriteArrayList<>();
for (String s : cowList) {
if (s.equals("x")) cowList.remove(s); // OK
}
Q: Which collection would you use for thread-safe key-value storage with high read concurrency?
ConcurrentHashMap - it provides excellent read concurrency (reads are lock-free) and segment-level locking for writes. For even higher read throughput, use CopyOnWriteArrayList for lists or ReadWriteLock for custom scenarios.
Concurrency
Key Concepts
- Thread safety: Synchronize access to shared mutable state
- Happens-before: Volatile, synchronized, locks, and concurrent collections establish happens-before edges
- Liveness: Deadlock, livelock, starvation
- Virtual threads: Lightweight threads for I/O-bound workloads (Java 21+)
Sample Questions
Q: Explain synchronized at method and block level.
// Method-level: synchronizes on this
public synchronized void increment() { count++; }
// Block-level: finer-grained, specifies lock object
public void increment() {
synchronized (this) {
count++;
}
}
// Static method: synchronizes on Class object
public static synchronized void reset() { count = 0; }
Q: What is a deadlock? How do you prevent it?
A deadlock occurs when two or more threads are blocked forever, each waiting for a resource held by the other.
// Deadlock scenario
Thread 1: synchronized(a) { synchronized(b) { ... } }
Thread 2: synchronized(b) { synchronized(a) { ... } }
// Prevention strategies:
// 1. Consistent lock ordering (always acquire a then b)
// 2. Lock timeout (tryLock with timeout)
// 3. Deadlock detection (ThreadMXBean)
Q: When would you use CompletableFuture vs virtual threads?
// CompletableFuture: chaining async operations
CompletableFuture.supplyAsync(this::fetchData)
.thenApply(this::transform)
.thenAccept(this::save)
.exceptionally(ex -> { logError(ex); return null; });
// Virtual threads: simple sequential code
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.submit(() -> {
var data = fetchData(); // Blocks but doesn't pin carrier
var transformed = transform(data);
save(transformed);
});
}
Use virtual threads for simple I/O-bound tasks (easier to write/debug). Use CompletableFuture when you need timeouts, composition, or combine multiple async results.
JVM Internals
Key Concepts
- Class loading: Bootstrap (rt.jar) -> Platform (JDK modules) -> Application (classpath)
- Runtime data areas: Method area (class metadata), Heap (objects), Stack (frames), PC registers
- Garbage collection: Young (Eden, S0, S1) -> Old (Tenured) -> Metaspace
- JIT compilation: Interpreted -> C1 (client) -> C2 (server); tiered compilation by default
- GC types: G1 (default), ZGC (sub-ms pauses), Shenandoah (concurrent compaction)
Sample Questions
Q: What happens when you call new MyObject()?
- Class loading: load, verify, prepare, resolve, initialize
MyObject - Heap memory allocated for object (including header: mark word + klass pointer)
- Fields initialized to default values (0, null, false)
- Constructor called (starting with Object constructor chain)
- Reference assigned to variable
Q: How does G1 GC work?
G1 divides the heap into regions (typically 2048, each 1-32 MB). It tracks which regions are most full of garbage and prioritizes collecting those first (garbage-first). It provides predictable pause times via the -XX:MaxGCPauseMillis flag. G1 compacts live objects into fewer regions during evacuation pauses.
Q: What JVM flags would you use to diagnose a memory leak?
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/path/to/dump.hprof
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xlog:gc*:file=gc.log
-verbose:class
Spring Boot
Key Concepts
- Auto-configuration:
@EnableAutoConfiguration+ spring.factories conditionally configures beans - Dependency injection: Constructor injection preferred;
@Autowiredis optional when single constructor - Actuator: Health, metrics, env, loggers, thread dump, heap dump endpoints
- Profiles:
application-{profile}.yml;spring.profiles.active - Exception handling:
@ControllerAdvice+@ExceptionHandler - Testing:
@WebMvcTest(controllers),@DataJpaTest(repositories),@SpringBootTest(integration)
Sample Questions
Q: Explain the Spring Bean lifecycle.
- Instantiate bean
- Populate properties (setter injection)
- Set bean name (BeanNameAware)
- Set bean factory (BeanFactoryAware)
- Pre-initialization (BeanPostProcessor postProcessBeforeInitialization)
- Call
@PostConstruct/InitializingBean.afterPropertiesSet() - Custom init method
- Post-initialization (BeanPostProcessor postProcessAfterInitialization)
- Bean ready for use
- Container shutdown:
@PreDestroy/DisposableBean.destroy()/ custom destroy method
Q: How would you configure a connection pool in Spring Boot?
spring:
datasource:
url: jdbc:postgresql://localhost:5432/mydb
hikari:
maximum-pool-size: 20
minimum-idle: 5
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
Q: What is the difference between @Component, @Service, @Repository, and @Controller?
All are @Component stereotypes that enable auto-detection. @Repository adds persistence exception translation. @Controller adds web request mapping support. @Service is a semantic marker for the service layer.
Microservices & Architecture
Key Concepts
- Service discovery: Eureka (client-side), Consul, Kubernetes DNS
- API Gateway: Spring Cloud Gateway, Zuul, Kong
- Circuit breaker: Resilience4J (state machine: closed -> open -> half-open)
- Distributed tracing: Micrometer + Zipkin/Jaeger (trace ID propagated across services)
- Event-driven: RabbitMQ, Kafka (message brokers for async communication)
- Saga pattern: Distributed transactions via choreographed or orchestrated sagas
Sample Questions
Q: How do you handle distributed transactions?
Use the Saga pattern. In an orchestrated saga, a coordinator service sends commands and handles compensating transactions on failure. In a choreographed saga, services emit events and react to events from other services.
Q: What is eventual consistency? When is it acceptable?
Eventual consistency means that given enough time without updates, all replicas will converge to the same value. It is acceptable for read-heavy workloads, social feeds, analytics, and any system where immediate consistency is not critical. Use strong consistency for financial transactions, inventory, and booking systems.
Q: How would you design a rate-limiting solution?
- Token bucket algorithm: each request consumes a token; tokens refill at a fixed rate
- Implement at API Gateway level (Spring Cloud Gateway's
RequestRateLimiter) - Use Redis with Lua scripts for atomic operations across instances
- Return
429 Too Many RequestswithRetry-Afterheader
System Design
Sample Questions
Q: Design a URL shortening service like TinyURL.
- API:
POST /shorten(returns short code),GET /{code}(redirects to long URL) - Storage: Use a distributed database (Cassandra for high write throughput)
- Code generation: Base62 encoding of a unique ID from a distributed ID generator (Snowflake)
- Caching: Redis for hot URLs (LRU eviction)
- Redirection: 301 (permanent) or 302 (temporary) redirect
- Analytics: Capture click events asynchronously to a message queue for processing
Q: Design a real-time leaderboard for a gaming platform.
- Data model: Player ID -> Score (stored in Redis Sorted Set)
- Operations:
ZADD leaderboard:game1 playerID score(update score) - Queries:
ZREVRANGE leaderboard:game1 0 9 WITHSCORES(top 10) - Real-time updates: WebSocket push when rank changes
- Partitioning: Shard by game ID; use Redis Cluster for horizontal scaling
- Persistence: Periodic snapshots to database for recovery
Behavioral Questions
The STAR Method
Structure your answers using Situation, Task, Action, Result.
Sample: Tell me about a challenging technical problem you solved.
- Situation: Our monolith application had a critical memory leak in production
- Task: Identify and fix the leak without affecting uptime
- Action: Enabled heap dump on OOM, analyzed with Eclipse MAT, found a static HashMap holding customer sessions that never expired, implemented a scheduled cleanup with
ScheduledExecutorServiceand switched to Guava Cache with expiration - Result: Memory usage stabilized at 40% of heap, zero OOM errors in the following 6 months
Practice Problems
Coding Challenge 1: Thread-Safe Counter
Implement a thread-safe counter that supports increment, decrement, and get operations. Compare synchronized, AtomicInteger, ReentrantLock, and LongAdder approaches.
Coding Challenge 2: LRU Cache
Implement an LRU cache with O(1) get and put operations. Use LinkedHashMap or a combination of HashMap and custom doubly-linked list.
Coding Challenge 3: Rate Limiter
Implement a token bucket rate limiter that allows N requests per second. Make it thread-safe and efficient.
Coding Challenge 4: Producer-Consumer
Implement a bounded buffer using wait()/notify() and compare with BlockingQueue.
Coding Challenge 5: JSON Validator
Write a recursive descent parser that validates a simplified JSON string (objects with string keys and string/number/boolean/null values).
Common Mistakes
1. Not Explaining Your Reasoning
Interviewers care more about your thought Process than the final answer. Think aloud, discuss tradeoffs, and ask clarifying questions.
2. Focusing Only on Syntax
Demonstrate understanding of principles: immutability, thread safety, performance implications, design tradeoffs.
3. Rushing the Solution
Take a moment to understand the problem, ask clarifying questions, sketch the approach before coding.
4. Ignoring Edge Cases
Always consider: null inputs, empty collections, concurrent access, integer overflow, negative values.
5. Not Testing Your Code
Walk through your solution with a sample input. Check off-by-one errors, loop termination, and exception paths.
FAQ
Final Project: Complete Interview Preparation
Create a study plan:
- Week 1-2: Review core Java (lessons 1-20). Re-implement collections and OOP examples.
- Week 3: Concurrency and JVM (lessons 21-30, 51-60). Write thread-safe examples.
- Week 4: Spring Boot and REST APIs (lessons 63-65). Build a small CRUD application.
- Week 5: System design and microservices (lessons 66). Practice 5 system design problems.
- Week 6: Practice coding challenges daily. Review behavioral questions. Do mock interviews.
Good luck with your Java journey!
What's Next
Congratulations on completing all 70 lessons of the Java tutorial series. You have covered everything from Java fundamentals to enterprise development and interview preparation. Continue building projects, contributing to open source, and exploring advanced topics like JVM performance tuning and Spring Cloud.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro