Loading...
Loading...
Java interview guide
Questions from the interview-preparation section: core Java, OOP, collections, output prediction and backend rounds. Every answer is short enough to say aloud, and every question links to the lesson that teaches it.
59 questionsLast updated
Yes. Only code that asks for the same lock is blocked; unsynchronized methods ignore the lock, which is why every access to shared state must be synchronized.
Lesson: synchronized, volatile and Race ConditionsAn atomic instruction that sets a variable to a new value only if it still holds an expected value, and reports whether it succeeded. It lets threads update shared data without locks, retrying when they lose a race.
Follow-up: What is the ABA problem? A value changes from A to B and back to A, so CAS sees no change. AtomicStampedReference adds a version to detect it.
Common mistake: Saying CAS locks the variable. CAS is lock-free; it retries if the value changed.
Lesson: synchronized, volatile and Race ConditionsBoth give mutual exclusion and are reentrant. ReentrantLock adds tryLock with a timeout, interruptible locking, optional fairness and multiple Condition objects, but you must call unlock() in a finally block. synchronized is simpler and releases automatically.
Follow-up: Why unlock in finally? If the code throws, the lock must still be released. synchronized does this automatically; ReentrantLock does not.
Common mistake: Forgetting unlock() in a finally block. One exception then leaves the lock held forever.
Lesson: synchronized, volatile and Race ConditionsNot from inside the JVM: a thread blocked on a monitor cannot be interrupted or timed out. You have to restart the application and fix the lock order. With ReentrantLock.lockInterruptibly or tryLock, a waiting thread can at least be interrupted or give up.
The application or one feature hangs, requests time out, CPU usage is low, and a thread dump shows threads stuck in BLOCKED or WAITING on locks held by each other.
Lesson: Deadlock: Cause and PreventionnewFixedThreadPool(n), newCachedThreadPool(), newSingleThreadExecutor(), newScheduledThreadPool(n), newWorkStealingPool() (a ForkJoinPool), and since Java 21 newVirtualThreadPerTaskExecutor().
Follow-up: When would you use a cached pool? For many short-lived tasks, because it reuses idle threads. It is risky under heavy load as the thread count is unbounded.
Common mistake: Recommending Executors factory methods for production without mentioning their unbounded queue or unbounded threads.
Lesson: Executors and Thread PoolsinvokeAll runs all the tasks and returns a list of Futures when all are done. invokeAny returns the result of the first task that completes successfully and cancels the rest.
A pool designed for divide-and-conquer tasks that split into subtasks, using work stealing: idle threads take tasks from busy threads' queues. Parallel streams and CompletableFuture default to its common pool.
A small per-thread area that holds the address of the bytecode instruction the thread is currently executing. Each thread needs its own because threads run different code at the same time.
Lesson: Stack vs Heap and Class LoadingLoading (read the bytes, create the Class object), linking (verification, preparation of static fields with default values, and resolution), and initialisation (running static initialisers and static blocks). Initialisation happens once, on first active use.
Follow-up: Which phase gives static fields their values? Initialisation. Preparation only sets default values such as 0 or null.
Common mistake: Saying a class is loaded and initialised at program start. Loading is lazy.
Lesson: Stack vs Heap and Class LoadingReferences the GC always treats as live: local variables and parameters in all thread stacks, static fields of loaded classes, active Thread objects, JNI references, and objects used as monitors by running synchronized code.
Follow-up: Name three kinds of GC roots. Local variables on a thread stack, static fields of loaded classes, and live threads. JNI references are also roots.
Common mistake: Naming only local variables. Static fields are roots too, which is why static collections leak.
Lesson: Garbage Collection and Memory LeaksIt divides the heap into many equal regions, each acting as Eden, survivor or old. It tracks how much garbage each region has and collects the regions with the most garbage first, trying to meet a pause-time goal set with -XX:MaxGCPauseMillis.
Follow-up: What is the pause goal? A target pause time set with -XX:MaxGCPauseMillis. G1 picks regions to meet it.
Common mistake: Saying G1 never pauses. It still has stop-the-world phases; they are shorter and controllable.
Lesson: Garbage Collection and Memory LeaksRunning clean-up after an object has been collected. Its get() always returns null; when the object is collected, the reference is put on a ReferenceQueue. java.lang.ref.Cleaner is built on this.
With a BlockingQueue I put a poison pill after the last item, and the consumer leaves its loop when it takes it. With several consumers I put one pill per consumer. For a thread I do not control, I call interrupt() and make the loop check the interrupt flag.
Follow-up: Why not Thread.stop()? It is deprecated and unsafe: it kills the thread at any point and can leave data half-updated.
Common mistake: Using Thread.stop() or System.exit(). Both are unsafe ways to end a worker.
Lesson: Practice: Concurrency & JVM DrillKeep critical sections small and lock only the shared update. Use ConcurrentHashMap, LongAdder or a ReadWriteLock instead of one big lock. Prefer immutable objects and thread confinement, so there is nothing to lock.
Lesson: Practice: Concurrency & JVM DrillFROM and JOIN, then WHERE, GROUP BY, HAVING, SELECT, DISTINCT, ORDER BY, and finally LIMIT. That is why an alias defined in SELECT cannot be used in WHERE.
Follow-up: Why can ORDER BY use an alias but WHERE cannot? The alias is created in SELECT. ORDER BY runs after SELECT, but WHERE runs before it.
Common mistake: Listing the order the clauses are written (SELECT first) instead of the order they run (FROM first).
Lesson: SQL and Database Design Questions1NF: atomic values, so a student's skills go in a separate table rather than a comma list. 2NF: no column depends on part of a composite key, so course_name does not belong in enrollments(student_id, course_id). 3NF: no column depends on another non-key column, so dept_name belongs in departments, not employees.
Follow-up: Is it always right to normalise to 3NF? No. Read-heavy reports may be denormalised on purpose to avoid joins, accepting some repeated data to keep reads fast.
Common mistake: Reciting the three definitions with no one-line example for each form.
Lesson: SQL and Database Design QuestionsAtomicity: a transaction is all or nothing. Consistency: constraints hold before and after. Isolation: concurrent transactions do not interfere. Durability: committed changes survive crashes, thanks to the redo log.
Follow-up: Which part of ACID does the redo log support? Durability: committed changes reach the redo log first, so they survive a crash.
Common mistake: Listing Atomicity, Consistency, Isolation and Durability with no example. A bank transfer makes every letter concrete.
Lesson: SQL and Database Design QuestionsexecuteQuery is for SELECT and returns a ResultSet. executeUpdate is for INSERT, UPDATE, DELETE and DDL and returns the affected row count. execute works for any statement and returns true if the result is a ResultSet.
Follow-up: Which method would you call for an INSERT? executeUpdate; it returns the number of rows changed. executeQuery on an INSERT throws an exception.
Common mistake: Using executeQuery for every statement. It is only for SELECT.
Lesson: JDBC, PreparedStatement and SQL InjectionA pool keeps a set of open database connections and lends them to requests, because opening a new connection each time is slow. HikariCP is the default in Spring Boot; settings include maximum pool size and connection timeout.
Follow-up: What does close() do on a pooled connection? The pool wraps the real connection, so close() returns it to the pool instead of disconnecting.
Common mistake: Saying a pool "makes queries faster". It saves the cost of opening connections and limits how many the database must serve.
Lesson: JDBC, PreparedStatement and SQL InjectionRaw JDBC needs repetitive code for connections, statements, mapping rows to objects, exceptions and transactions. JdbcTemplate removes the boilerplate, and JPA/Hibernate maps objects to tables and generates SQL, while still using JDBC underneath.
Follow-up: Does JPA replace JDBC? No. Hibernate still uses JDBC underneath; JPA only removes the repetitive mapping and SQL writing.
Common mistake: Saying raw JDBC is "bad". It is fine for small jobs; frameworks save repeated code.
Lesson: JDBC, PreparedStatement and SQL InjectionPOST asks the server to create a resource in a collection, and the server picks the id; it is not idempotent. PUT sends the complete resource to a known URL and replaces it; it is idempotent.
Lesson: REST Principles, HTTP Methods and Status CodesA session app stores login state on the server and sends a session id cookie; the server looks it up on each request. A token API, such as one using JWT, puts the identity in a signed token the client sends in the Authorization header, so the server keeps no session.
Spring Boot is built on Spring and makes apps quick to start: starters bundle dependencies, auto-configuration sets up beans based on the classpath, an embedded server (Tomcat) runs the app as a jar, and Actuator adds health and metrics. Plain Spring needs that setup by hand.
Lesson: Dependency Injection, Beans and Spring BootA class that declares beans through @Bean methods. Spring proxies it so that calling one @Bean method from another returns the same singleton instead of a new object.
@Controller methods return view names rendered by a template engine into HTML. @RestController adds @ResponseBody to every method, so return values are written to the HTTP body, usually as JSON.
Follow-up: What does a @Controller method return for a web page? A view name such as "student", which a template engine like Thymeleaf renders to HTML.
Common mistake: Saying @RestController is only "for JSON". It is @Controller plus @ResponseBody; the body format comes from the message converters.
Lesson: Dependency Injection, Beans and Spring BootA class mapped to a table, marked @Entity, with a primary key field marked @Id and a no-argument constructor (it may be protected). It must not be final if Hibernate needs to proxy it for lazy loading.
Associated data is loaded only when first accessed. Hibernate replaces the related entity or collection with a proxy that runs a query on first use, provided the persistence context is still open.
Follow-up: What does a lazy association contain before it is loaded? A Hibernate proxy. The first access runs the query, if the session is still open.
Common mistake: Saying lazy loading is "always better". It saves unneeded queries, but it causes N+1 and LazyInitializationException if misused.
Lesson: JPA Entities, Lazy Loading and the N+1 ProblemIt passes operations from a parent to its children, for example cascade = CascadeType.ALL on an order's items so saving or deleting the order saves or deletes the items. orphanRemoval = true deletes items removed from the collection.
Authentication checks who you are, for example with a password or a token. Authorisation checks what you are allowed to do, such as whether you have the ADMIN role. Authentication always happens first.
Follow-up: Which comes first? Authentication. The app must know who you are before it can decide what you may do.
Common mistake: Using the words as synonyms. They are two checks with two different failure codes.
Lesson: Authentication, JWT and Password HashingBCrypt only uses the first 72 bytes of the password, and non-English characters take several bytes each. In Spring Security 7, encode rejects longer passwords with an error, so sign-up validation should limit the length.
A long-lived token, stored server-side or tracked there, that the client exchanges for a new short access token. Revoking it ends the session. Rotating it on every use helps detect theft.
Lesson: Authentication, JWT and Password Hashingexp claim?Not by default: JwtTimestampValidator rejects an exp that has passed (with 60 seconds of clock skew) but accepts a missing one. Always set exp when issuing, and call setAllowEmptyExpiryClaim(false) on the validator if tokens from elsewhere must have it.
when().thenReturn() and verify()?when(...).thenReturn(...) sets up what the mock returns (stubbing, in Arrange). verify(...) checks afterwards that a method was called, how many times and with which arguments (in Assert).
Follow-up: What does verify(mock, never()) check? That a method was not called, for example that save was never called when validation failed.
Common mistake: Verifying every call on every mock. Check the results and the interactions that matter.
Lesson: Testing, Design Patterns and Basic System Design QuestionsA method or class that creates objects so the caller does not name the concrete class. List.of(...) returns a hidden implementation, and a PaymentFactory.forMethod("UPI") returns the right processor.
A cache keeps copies of hot data in fast memory to avoid repeated slow reads. With cache-aside, the app reads the cache first; on a miss it reads the database, stores the result with a TTL, and on updates it deletes the cached entry.
Follow-up: What happens to the cache when the data is updated? The app deletes (invalidates) the cached entry, so the next read loads the fresh value. A TTL is a safety net, not the plan.
Common mistake: Caching without any invalidation or TTL. Users then see stale data for ever.
Lesson: Testing, Design Patterns and Basic System Design QuestionsThey scale differently. A URL shortener might have 12 writes and 1,200 reads per second, so the design focuses on caching and read replicas rather than on write throughput.
Lesson: Testing, Design Patterns and Basic System Design QuestionsI check that the stored hash and the PasswordEncoder match, for example a plain password saved in the database, or a hash without the {bcrypt} prefix. I also check that the user is enabled, that the e-mail is trimmed and compared in the same case, and that the password is not longer than 72 bytes.
Follow-up: How do you test it without exposing the password? A unit test calls encoder.matches(raw, stored) for a known pair. Never log the raw password.
Common mistake: Printing the password to the log to see what arrived.
Lesson: Practice: Java Backend Interview DrillAll three, for different rules. The controller checks the shape of the input with @Valid. The service checks business rules such as stock and state. The database enforces constraints such as unique and not null as the last safety net.
Common mistake: Putting every rule in the controller and nowhere else.
Lesson: Practice: Java Backend Interview DrillIf it has none, say so: "No real users; it is a portfolio project." Then add what you did measure, for example "I tested the order endpoint with 100 parallel requests and stock never went below zero." Never invent numbers: one follow-up question exposes them.
Follow-up: How do you know it would cope with more? "I do not know for sure. At 100 parallel requests on my laptop the order endpoint kept stock correct. For real scale I would measure with a load-test tool first."
Common mistake: Inventing a number. The next question, "how do you track them?", ends the story and costs you the trust you built in the first minute.
Lesson: A Short Project Pitch: Problem, Solution, Your RoleName who had which pain: "Small shops near my college take orders on WhatsApp and often sell items that are out of stock." One sentence, a real situation, no technology yet.
Lesson: A Short Project Pitch: Problem, Solution, Your Role"I needed REST endpoints, database access, validation and security. Spring Boot gives all of these through starters and auto-configuration, with an embedded server. The cost is a slower start-up and some hidden configuration; for a tiny single-endpoint service a lighter option would also work."
Follow-up: What does auto-configuration actually do? "It looks at the libraries on the classpath and my properties and creates the beans I would otherwise write by hand, for example a DataSource when a MySQL driver and a URL are present. I can still override any of them."
Common mistake: Saying "it is popular" or "the course used it". Start from what the project needed.
Lesson: Explaining Your Design and Tech Choices"Requests that need it fail; the connection pool times out and my handler returns a 500 or 503 with a safe message, without exposing details. The app recovers when the database is back, because the pool makes new connections. For real high availability you would need a replica that can take over."
Follow-up: How would you make the database highly available? "Run a primary with a replica that can take over automatically, keep regular backups, and let the app reconnect through the connection pool."
Common mistake: Saying "it will never go down". Every system fails; the answer is about what happens next.
Lesson: Explaining Your Design and Tech Choices"I would cache hot reads like the product catalogue with Spring's cache support and Caffeine, and clear an entry when that product is updated. What can go wrong: stale prices if I forget to evict, memory growth without a size limit, and inconsistent data across several app copies with a local cache."
Lesson: Explaining Your Design and Tech ChoicesSay so, then reason it out loud: "I do not remember adding this, but reading it, it seems to set the time zone for dates, because the API shows times with +05:30." Guessing confidently and being wrong is much worse than honest reasoning.
Follow-up: How would you find out? "I would read the code and its tests, search where it is used, check git blame and the commit message, and run it in the debugger."
Common mistake: Guessing confidently and being wrong. Honest reasoning out loud scores much better.
Lesson: Challenges You Solved and Did-You-Build-It Questions"At first the controller checked stock and saved the order. When I added cancel, I needed the same rules elsewhere, and stock and order were not in one transaction. I moved the logic into a @Transactional service method; the controller became a thin layer."
"One short line, about 72 characters at most, in the imperative, saying what changed: fix(orders): reject negative quantity. A type prefix makes the history easy to scan. 'update' or 'final changes' tells the next reader nothing."
Follow-up: Do you use Conventional Commits? Why? "Yes: feat, fix, test, docs. The history is easy to scan, and tools can build a changelog from it."
Common mistake: Messages like "update" or "final changes": nobody can find a change later, including you.
Lesson: Linking Answers to Your GitHub CodeGit is the version control tool on your computer that records commits. GitHub is a website that hosts Git repositories online and adds pull requests, issues and profiles.
Lesson: Linking Answers to Your GitHub Code"From the README: run steps, how to run tests, and the branch and commit message style. In a team I would add a short CONTRIBUTING note and protect main so changes come through reviewed pull requests."
"Right now the last save wins, so one admin's change could be lost silently. I would add optimistic locking with a @Version column: the second save fails with a conflict, and the API returns 409 so that admin can reload and retry."
Follow-up: How does @Version work? "Hibernate adds the version to the update, ... WHERE id = ? AND version = ?. If another save already changed it, no row updates and Hibernate throws an optimistic lock exception."
Common mistake: Saying "the database handles it". By default the last save silently wins.
Lesson: Practice: Project Explanation Mock"Only a PLACED order can be cancelled. In one transaction the status becomes CANCELLED and every item's quantity goes back into stock. Cancelling a shipped order returns 409 invalid-state."
Lesson: Practice: Project Explanation Mock"final makes a variable unchangeable once set, a method not overridable, or a class not extendable. finally is a block that runs after try and catch, used for clean-up. finalize was an old clean-up hook called by the garbage collector; it is deprecated and should not be used."
Common mistake: Mixing the three up because they sound alike. final is a keyword, finally is a block that always runs, and finalize is an old method that the garbage collector may call. Give one sentence for each.
Lesson: Mock Round: Core Java, OOP and DSA (Stage 1-2)"Autoboxing uses Integer.valueOf, which caches objects only from -128 to 127 by default. 128 creates two different objects, so == compares references and gives false. Use equals for wrapper values."
Follow-up: How would you compare two Integer objects correctly? Use equals, or unbox to int before comparing. == on Integer compares references and only works by luck inside the cache range.
Lesson: Mock Round: Core Java, OOP and DSA (Stage 1-2)"Fetching a collection with JOIN FETCH while paging makes Hibernate load all rows and page in memory, with a warning, because joined rows break SQL LIMIT. The usual fix is to page the parent ids first, then fetch their collections in a second query."
Lesson: Mock Round: Java Backend Role"Atomicity: all or nothing. Consistency: rules and constraints hold before and after. Isolation: parallel transactions do not see each other's half-done work, depending on the isolation level. Durability: committed data survives a crash."
Lesson: Mock Round: Java Backend RoleState the current complexity, then look for the bottleneck: "This is O(n²) because of the inner loop. If I store what I have seen in a HashSet, the inner search becomes O(1), so the whole thing is O(n) with O(n) extra space."
Follow-up: What is the cost of the better idea? State both: time drops from O(n²) to O(n), and space rises from O(1) to O(n) for the set.
Common mistake: Jumping to code for the new idea. First name the bottleneck, say the new idea and its cost, and only then change the code.
Lesson: Self-Review Checklist and Common Rejection Reasons"Yes, it is expected. Asking about input size, empty input, duplicates and the output format shows care and often changes the right approach. I keep it to the questions that matter, then confirm my understanding with an example."
Lesson: Self-Review Checklist and Common Rejection ReasonsPick a real but not critical gap with an action: "Advanced concurrency. I understand threads, synchronized and executors, and I am working through CompletableFuture examples now." Avoid naming a core basic as your weakness.
Common mistake: Naming a core basic ("Java, OOP") or saying you have no weakness. Choose a real advanced gap and a concrete action already started.
Lesson: A Revision Plan for the Last Week Before InterviewsRejoin quickly, switch to your backup hotspot, and if needed message the recruiter or the meeting chat at once. When back, say briefly where you were and continue; do not panic or apologise at length.
Common mistake: Going quiet or leaving the call without a word. Rejoin fast, use the backup, message the recruiter, and say briefly where you were. Calm recovery is noticed.
Lesson: A Revision Plan for the Last Week Before InterviewsEach lesson has quizzes, practice and more interview questions on the same topic.
Open the first lesson