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.
61 questionsLast updated
Online tests grade code on hidden test cases, so handling edge cases such as empty input or repeated values matters as much as the main logic. I tested my solutions on small tricky inputs before submitting, instead of only the sample.
Follow-up: How do you test a solution before submitting? I run the sample, then my own small cases: empty input, one element, duplicates, negatives and the largest allowed size. I also check the exact output format.
Common mistake: Saying "I was lucky" or only "I practised a lot". Name the habit: testing edge cases beyond the sample.
Lesson: Interview Rounds: Online Test, Technical and ManagerialI stay calm and keep answering clearly, because one weak answer is not the whole round. If I need time, I say "Let me think for a moment", and I use the next question to recover.
Common mistake: Getting flustered or apologising again and again. Interviewers score the whole round, so a calm recovery is a positive signal.
Lesson: Interview Rounds: Online Test, Technical and ManagerialAlways ask one or two real questions, for example: "What would a fresher work on in the first six months?" or "How is training organised for new joiners?" Avoid asking only about salary in a technical round.
Follow-up: What would you do with that answer in your first month? I would use it to plan: learn the codebase and tools, fix a small bug, and ask my mentor for feedback each week.
Common mistake: Saying "No questions" or asking only about salary. A real question shows interest in the work.
Lesson: Interview Rounds: Online Test, Technical and ManagerialI thank them, restate the hint so we agree on it, and explain how it changes my approach before coding. Using a hint well is a positive signal; ignoring it is a negative one.
Common mistake: Ignoring the hint or taking it silently. Restate it so you both agree, then explain how it changes your plan.
Lesson: What Interviewers Look For Beyond the Right AnswerUse a real one, for example: "My marks average was wrong because I used integer division; sum / count dropped the decimal. I learned to cast to double and to test with values that do not divide evenly."
I am revising Java concurrency, executors and CompletableFuture, and I am adding asynchronous order emails to my ShopLite project to use them.
Common mistake: Saying "I keep learning new things". Name something specific and recent.
Lesson: Choosing What to Revise for Your Target RoleI keep a tracker with a confidence score and a note for each topic. Each day I pick the two lowest scores, re-learn them, do a few practice questions and update the scores after a short self-test.
Lesson: Choosing What to Revise for Your Target RoleFor a fresher role, I focused on the topics that are asked most: core Java, OOP, collections, DSA and projects. I know the basics of caching and load balancing from my course, and I am happy to discuss them at that level.
Lesson: Choosing What to Revise for Your Target RoleChecked exceptions, such as IOException, must be caught or declared with throws, and the compiler checks this. Unchecked exceptions extend RuntimeException, such as NullPointerException, and are not checked. Checked exceptions are for recoverable outside problems; unchecked ones usually mean a bug.
Follow-up: Give one example of each. Checked: IOException when reading a file. Unchecked: NullPointerException, usually a bug in the code.
Yes, if I say clearly that it is a guess and show how I reached it. What I avoid is stating a guess as a fact, because one follow-up question exposes it and the interviewer then doubts my other answers too.
Lesson: Practice: Framing Interview Answersjavac do?javac is the Java compiler. It checks the source for errors such as wrong types or missing semicolons and turns each class into a .class file of bytecode. It does not run the program.
The class loader subsystem, which loads and links classes; the runtime data areas, such as the heap, the method area and one stack per thread; and the execution engine, with the interpreter, the JIT compiler and the garbage collector.
Follow-up: Which part stores objects? The heap, shared by all threads and managed by the garbage collector. Each thread also has its own stack for method calls.
Lesson: JDK, JRE, JVM and Platform Independence Questions.java file contain several classes?Yes, but at most one top-level class can be public, and the file must be named after it. javac produces a separate .class file for every class in the file.
A wrapper class is the object version of a primitive: Byte, Short, Integer, Long, Float, Double, Character and Boolean. They live in java.lang, are immutable, and add useful methods such as Integer.parseInt.
Integer.parseInt and Integer.valueOf?parseInt("42") returns a primitive int. valueOf("42") returns an Integer object, using the cache for small values. Both throw NumberFormatException for text that is not a number.
boolean be converted to an int in Java?No. Unlike C, Java has no conversion between boolean and numbers, not even with a cast. You write flag ? 1 : 0 instead.
== and equals for strings?== checks whether two references point to the same object. equals checks whether the characters are the same. For comparing text, always use equals.
Follow-up: Why does == sometimes return true for strings? Because identical literals share one pooled object, so both references are the same. It is an accident of the pool, not a rule you can rely on.
Common mistake: Saying "== checks values for Strings". It checks references. A tests-pass-by-luck answer with literals shows you do not know about the pool.
Lesson: String Immutability, the String Pool and == vs equals"ja" + "va" == "java" true?Both parts are literals, so the compiler joins them at compile time into the single constant "java", which is pooled. Both sides are the same pooled object.
Follow-up: What if part is declared final String part = "ja"? Then part + "va" is also a compile-time constant, so it is pooled and == with "java" becomes true.
s = s + "x" work?It creates a new String with the joined text and points s at it. The old string is unchanged; if nothing else refers to it, it becomes garbage.
+ inside a loop slow?Each s = s + x creates a new String and copies all the old characters into it. Over n iterations that is about 1 + 2 + ... + n character copies, O(n²) work, plus many short-lived objects. A StringBuilder appends into one growing buffer, which is O(n) overall.
Follow-up: How would you fix it, and what becomes the cost? Use a StringBuilder and call append in the loop. The total work drops from O(n²) to O(n).
Common mistake: Saying "because Strings are immutable" and stopping. Explain the cost: every pass copies all earlier characters and creates a new object.
Lesson: String vs StringBuilder vs StringBufferNo. It inherits Object.equals, which compares references, so two builders with the same text are not equals. Compare a.toString().equals(b.toString()), a.compareTo(b) == 0 (Java 11+) or "text".contentEquals(sb).
Follow-up: Then how do you compare two builders? Compare a.toString().equals(b.toString()), or use a.compareTo(b) == 0 from Java 11. Never rely on a.equals(b).
Common mistake: Saying "yes, it compares the text because println prints the text". toString is overridden, but equals is not.
Loop over the characters and append only the ones that are not spaces: for (char c : s.toCharArray()) if (c != ' ') sb.append(c); then sb.toString(). s.replace(" ", "") is the one-line alternative.
final, synchronized or with String... args?Yes to all three. final and synchronized are allowed modifiers, and varargs String... args is accepted as the entry point because it compiles to String[].
Yes. final locks the reference, not the object. final List<String> names = new ArrayList<>(); names.add("Asha"); works; names = new ArrayList<>(); does not compile.
Follow-up: How would you make the list itself unchangeable? Use List.of(...) or Collections.unmodifiableList(list). Then add throws UnsupportedOperationException.
Common mistake: Saying "a final object cannot change". final only locks the reference. The object's own fields or list items can still change.
No. Serialization saves an object's state, and static fields belong to the class, so they are skipped like transient fields. After deserialization a static field simply has whatever value the class currently holds.
arr = new int[5];?Only the parameter now points to a new array. The caller's array is unchanged. Changes made to arr[...] after that line affect the new array, not the caller's.
Follow-up: How does Arrays.sort(arr) still work then? It changes the elements inside the shared array object, which is a mutation, not a reassignment of the parameter.
No. Only the reference, a few bytes, is copied, not the object. That is why passing large lists or arrays is cheap.
Lesson: Is Java Pass by Value or Pass by Reference?Checked exceptions, such as IOException and SQLException, must be caught or declared with throws; the compiler enforces it. Unchecked exceptions, RuntimeException and its subclasses such as NullPointerException, are not checked by the compiler and usually mean a programming bug.
Follow-up: Which one would you use for a missing file, and which for a null argument? A missing file is checked (FileNotFoundException) because the caller can recover. A null argument is a bug, so it is unchecked (IllegalArgumentException or NullPointerException).
Common mistake: Saying "checked exceptions happen at compile time". They are thrown at run time; the compiler only forces you to handle or declare them.
Lesson: Exceptions: Checked vs Unchecked, finally, throw vs throwsIn reverse order of opening: the last resource declared is closed first. Closing happens before any catch or finally block of the same statement runs.
getMessage() and getCause()?getMessage() returns the text given to the constructor. getCause() returns the wrapped exception if chaining was used, or null.
No: primitives and static members are not objects.
Lesson: Practice: Core Java Rapid-Fire DrillNo; it compares references. Compare toString() values instead.
A try that closes AutoCloseable resources automatically, in reverse order, even on exceptions.
Encapsulation is about protecting data inside a class: private fields plus methods that check rules. Abstraction is about hiding implementation behind a simple contract, usually an interface or abstract class. Encapsulation hides the data; abstraction hides the complexity.
Follow-up: Can one class show both? Yes. UpiPayment keeps its transaction log private (encapsulation) and is used only through Payment (abstraction).
Common mistake: Saying they are the same idea, or only "private versus interface". Say what each one hides: encapsulation hides data, abstraction hides implementation.
Lesson: The Four Pillars of OOP with Your Own ExamplesTo avoid the diamond problem: if C extends both A and B and both define show() or a field, which one does C get? Java avoids this ambiguity for state and implementation by allowing only one superclass.
Follow-up: Then how does a class get several types? By implementing several interfaces. If two defaults clash, the class overrides the method and picks one with Payable.super.describe().
Common mistake: Saying "Java has no multiple inheritance". Always add "of classes"; interfaces give multiple inheritance of type.
Lesson: The Four Pillars of OOP with Your Own ExamplesReuse through inheritance and composition, easier change because implementation is hidden behind interfaces, safer code because objects protect their own state, and models that match the real problem, which makes large code bases easier to understand.
Lesson: The Four Pillars of OOP with Your Own ExamplesNo. Private methods are not inherited, so a method with the same name in the subclass is a new, unrelated method. A parent method calling its private helper always runs the parent's helper.
Common mistake: Saying private methods can be overridden "only inside the class". A private method is invisible to subclasses, so a same-named method is a brand new one.
Lesson: Overloading vs Overriding and Their RulesNo, overriding works without it. But it is strongly recommended, because it turns silent mistakes into compile errors and makes the intent clear to readers.
Lesson: Overloading vs Overriding and Their RulesNo. An instance method cannot be overridden by a static one, and a static method cannot be overridden by an instance one; both are compile errors.
Lesson: Overloading vs Overriding and Their RulesYes, and it is common: an interface for the contract (Payment), an abstract class implementing it with shared code (AbstractPayment with logging and validation), and concrete classes extending that. The JDK does this with List, AbstractList and ArrayList.
Follow-up: Name an example from the JDK. List is the interface, AbstractList holds shared code, and ArrayList is the concrete class.
A helper that belongs to the interface itself, called as InterfaceName.method(). It is not inherited by implementing classes, so F.twice(2) fails with "cannot find symbol" while Fee.twice(2) works. Example: Comparator.comparing.
Common mistake: Saying an implementing class inherits the static method. It does not; call it as InterfaceName.method().
Cloneable have no clone() method?It is a marker interface: it only tells Object.clone() that cloning is allowed; without it, clone() throws CloneNotSupportedException. This design is widely considered a mistake, which is why copy constructors are often preferred.
When there is a true IS-A relationship and the subclass can be used anywhere the parent is expected without surprises (Liskov substitution), when the parent is designed and documented for extension, or when a framework expects you to extend a base class, such as a custom exception extending RuntimeException.
Follow-up: How do you test it in one question? Ask: "Does every inherited public method still make sense on the child?" If you must block methods or throw UnsupportedOperationException, use composition.
Lesson: Composition vs InheritanceThe part is a field of an interface type, so you can give it a different implementation, through a constructor or setter, while the program runs, for example switching a Car's Engine from petrol to electric. Inheritance fixes behaviour when the class is written.
Follow-up: Which pattern is this? Strategy: the held object is a strategy that can be swapped. Decorator wraps the object to add behaviour instead.
Lesson: Composition vs InheritanceEqual objects usually get different identity hash codes, so a HashSet stores both as duplicates and contains with an equal object returns false. Lists still work, because ArrayList.contains only uses equals.
Follow-up: Does ArrayList.contains still work? Yes, it uses only equals. That is why the bug hides until the class is put in a HashSet or used as a HashMap key.
Common mistake: Saying HashSet throws an exception. Nothing fails: it silently keeps duplicates and contains returns false.
Lesson: The equals and hashCode ContractIt is an odd prime, so multiplying spreads values well and reduces collisions, and 31 * x can be computed as (x << 5) - x. String.hashCode uses it: s[0]*31^(n-1) + ... + s[n-1].
equals(Student other) signature a bug?It overloads instead of overriding equals(Object), so collections never call it. Use @Override public boolean equals(Object o); the annotation catches the mistake at compile time.
List.copyOf vs Collections.unmodifiableList: what is the difference?List.copyOf(list) makes an independent, unmodifiable copy, so later changes to the original do not show. Collections.unmodifiableList(list) is only a read-only view: callers cannot change it, but whoever holds the original list still can, and the view shows those changes.
Follow-up: Which is safer for a field? List.copyOf, because later changes to the original list do not show up in it.
Common mistake: Saying both are the same. unmodifiableList is only a view; whoever holds the original list can still change what you see.
A shared immutable object can be handed to many callers without copying, because nobody can change it. Integer.valueOf caches -128 to 127 and the string pool shares literals for exactly this reason.
String, all wrapper classes (Integer, Long and so on), BigInteger, BigDecimal, the java.time classes (LocalDate, LocalDateTime, Instant, Duration), and the lists from List.of.
No. A class can have many methods as long as they all serve one purpose. FeeCalculator might have tuition, hostel and total; they all change for the same reason.
Yes. Splitting tiny programs into many interfaces and classes adds indirection without benefit. Apply the principles where change is likely; a simple utility can stay simple.
Follow-up: How do you decide when to apply a principle? Apply it when you feel the pain: a class that changes for many reasons, or an if-else that grows with every new case.
Common mistake: Saying SOLID is always required. Over-applying it adds indirection with no benefit.
Lesson: SOLID in One Minute EachHashSet<Customer> shows the same customer twice. How do you debug it?First I check that equals takes an Object and has @Override; equals(Customer) is an overload that sets never call. Then I check that hashCode exists and uses exactly the fields equals compares. Last, I print the two hash codes: if they differ for equal customers, the contract is broken.
Common mistake: Switching to a List to hide the problem. That removes the duplicate check instead of fixing the class.
Lesson: Practice: OOP Interview DrillReciting definitions without an example, mixing up encapsulation and abstraction, calling overloading run-time polymorphism, forgetting hashCode when overriding equals, calling a record deeply immutable, and answering "always composition" or "always inheritance". I avoid them by giving the rule, one tiny example and the reason.
Arrays.asList returns a fixed-size list backed by the array: set works and writes through to the array, but add and remove throw. List.of (Java 9+) returns an unmodifiable list: every change throws, and it does not allow null elements. If I need a growable list, I copy either one into new ArrayList<>(...).
Follow-up: How do you get a growable list from either one? Copy it: new ArrayList<>(list). The copy is a normal ArrayList, so add and remove work. The original stays fixed-size or unmodifiable.
Common mistake: Saying Arrays.asList and List.of behave the same. asList allows set and nulls; List.of allows neither, and it is a separate copy rather than a view of the array.
LinkedList. Each element needs a node object with an item reference and two links plus an object header, roughly 24 bytes or more on a typical 64-bit JVM. ArrayList needs about one reference slot per element, plus some unused capacity.
Lesson: ArrayList vs LinkedListIt is an array of buckets. On put, it takes hashCode, spreads it with h ^ (h >>> 16), finds the bucket with (n - 1) & hash, and then either replaces the value of an equal key or adds a new node. On get, it goes to the same bucket and compares the hash and then equals, so lookups are O(1) on average.
Follow-up: Why is get O(1) on average and not always? It walks only one bucket. With a good hash the chains stay short, so the work does not depend on n. If many keys collide, that one bucket gets long and the lookup slows down.
Common mistake: Saying "the key is used as the array index" or skipping equals. Hashing only picks the bucket; equals picks the exact key inside it.
The previous value for that key, or null if there was none (or the old value was null). It is a quick way to know whether you replaced something.
Loop over entrySet() so each entry gives both key and value in one step, or use map.forEach((k, v) -> ...). Looping over keySet() and calling get does an extra lookup per key.
In Java 8 and later, reads mostly take no lock, and a write locks only the bucket it touches, using a compare-and-swap for empty buckets. Methods like merge, compute and computeIfAbsent do the read-and-update as one atomic step, so counters and caches stay correct.
Follow-up: Does that make every compound action safe? No. Each call is safe alone, but a check-then-put made of two calls is still a race. Use the atomic methods putIfAbsent, merge and computeIfAbsent.
Common mistake: Saying ConcurrentHashMap is fully synchronized like Hashtable. It uses finer locking, and that is exactly why it is faster.
Lesson: HashMap vs TreeMap vs LinkedHashMap (and ConcurrentHashMap)No, they are live views backed by the original TreeMap. Changes to either side show in the other, and adding a key outside the view's range throws IllegalArgumentException.
Each lesson has quizzes, practice and more interview questions on the same topic.
Open the first lesson