Skip to content
Laviyx Learn

Try

Java Interview Questions

Frequently asked Java interview questions on OOP, strings, collections, exceptions, concurrency and modern Java, with hints, full answers and the reasoning interviewers look for.

18 questions · Updated

  1. 1.What is the difference between the JDK, JRE and JVM?

    BeginnerConceptPlatform
    Show hint

    Which one do you need to run programs, and which one to write them?

    Show solution
    • The JVM runs Java bytecode (and JIT-compiles hot code to native machine code).
    • The JRE is the JVM plus the standard libraries: everything needed to run Java programs.
    • The JDK is the JRE plus development tools such as javac, jar and javadoc: what you install to write Java.

    javac compiles .java source to .class bytecode, which any JVM can run, which is the basis of "write once, run anywhere".

  2. 2.What is the difference between == and equals()?

    BeginnerConceptObjects
    Show hint

    What does == compare for objects?

    Show solution

    For primitives, == compares values. For objects, == compares references (is it the same object?), while equals() compares contents as defined by the class.

    Java
    String a = new String("java");
    String b = new String("java");
    a == b;        // false: two different objects
    a.equals(b);   // true: same text

    Always compare strings, wrapper objects (Integer) and other objects with equals.

  3. 3.Why is String immutable, and what are the benefits?

    BeginnerConceptStrings
    Show hint

    Think about the string pool, security and threads.

    Show solution

    A String can never change after creation; methods like replace return new strings. Benefits:

    • Literals can be shared safely in the string pool, saving memory.
    • Values used as class names, file paths, URLs or map keys cannot be altered by other code.
    • Immutable objects are automatically thread-safe.
    • The hash code can be cached, making strings fast HashMap keys.

    The trade-off is that repeated concatenation creates many objects, which is why StringBuilder exists.

  4. 4.Is Java pass by value or pass by reference?

    BeginnerConceptMethods
    Show hint

    What exactly is copied when you pass an object?

    Show solution

    Java is always pass by value. For objects, the value copied is the reference. So a method can modify the object's contents through its copy of the reference, but assigning a new object to the parameter does not affect the caller's variable:

    Java
    static void modify(List<String> list) {
        list.add("added");          // visible to the caller
        list = new ArrayList<>();   // only the local copy changes
    }
  5. 5.What does the static keyword mean?

    BeginnerConceptClasses
    Show hint

    Does a static member belong to an object?

    Show solution

    A static member belongs to the class, not to individual objects. A static field is shared by all instances; a static method is called on the class (Math.max(a, b)) and has no this, so it cannot access instance fields directly. main is static so the JVM can call it without creating an object. Static nested classes do not hold a reference to an outer instance.

  6. 6.What is the difference between overloading and overriding?

    BeginnerConceptOOP
    Show hint

    One is decided at compile time, the other at run time.

    Show solution
    • Overloading: several methods with the same name but different parameter lists; the compiler picks one from the argument types (compile time).
    • Overriding: a subclass replaces an inherited method with the same signature; the JVM picks the implementation from the actual object (run time, dynamic dispatch). Use @Override to let the compiler check it.
  7. 7.What is the difference between an abstract class and an interface?

    IntermediateConceptOOP
    Show hint

    Consider state, constructors, and how many of each a class can have.

    Show solution
    Abstract classInterface
    Instance fields / stateYesNo (only constants)
    ConstructorsYesNo
    Methods with bodiesYesdefault, static and private methods
    A class can extend / implementOneMany

    Use an interface to define a capability or type (and to declare variables), and an abstract class to share state and code among closely related classes.

  8. 8.Why must you override hashCode() when you override equals()?

    IntermediateConceptObjects
    Show hint

    How does a HashMap find a key?

    Show solution

    Hash-based collections first use hashCode() to choose a bucket and then equals() to find the key in it. The contract says equal objects must have equal hash codes. If you override only equals, two equal objects usually land in different buckets, so HashSet.contains and HashMap.get fail to find them. Override both together (IDEs generate them), or use a record, which generates both from its components.

  9. 9.How does HashMap work internally?

    IntermediateConceptCollections
    Show hint

    Buckets, collisions and resizing.

    Show solution

    A HashMap holds an array of buckets. put computes the key's hashCode(), mixes its bits, and maps it to a bucket index. Keys in the same bucket are stored in a linked list, which becomes a balanced tree when a bucket gets large (Java 8+), keeping the worst case at O(log n). get follows the same path and compares keys with equals. When the size exceeds capacity × load factor (0.75), the table doubles and entries are redistributed. Average get/put is O(1). Keys should be immutable, because a key whose hash changes after insertion is lost.

  10. 10.When would you use ArrayList vs LinkedList?

    IntermediateConceptCollections
    Show hint

    Compare index access, insertion and memory.

    Show solution

    ArrayList uses a resizable array: O(1) get(i), amortized O(1) append, O(n) insert/remove in the middle, and compact memory with good cache behaviour. LinkedList uses linked nodes: O(1) insert/remove at the ends (or at an iterator), O(n) get(i), and much more memory per element. ArrayList is the right default almost always; for queues and stacks use ArrayDeque.

  11. 11.What is the difference between checked and unchecked exceptions?

    IntermediateConceptExceptions
    Show hint

    Which ones does the compiler force you to handle?

    Show solution

    Checked exceptions extend Exception (but not RuntimeException), for example IOException; the compiler forces you to catch them or declare them with throws, because they represent recoverable conditions. Unchecked exceptions extend RuntimeException, for example NullPointerException and IllegalArgumentException; they usually signal programming errors and need not be declared. Errors such as OutOfMemoryError are serious JVM problems that applications normally should not catch.

  12. 12.What does this code print?

    BeginnerOutput predictionStrings
    Show hint
    • is evaluated left to right, and becomes concatenation once a String is involved.
    Show solution
    Java
    System.out.println(1 + 2 + "3" + 4 + 5);
    System.out.println("Sum: " + (4 + 5));

    It prints 3345 and then Sum: 9. In the first line, 1 + 2 is integer addition (3); then 3 + "3" becomes the string "33", and every later + concatenates: "334", "3345". Parentheses force the numeric addition in the second line.

  13. 13.What does this code print, and why?

    IntermediateOutput predictionWrapper classes
    Show hint

    Integer objects for small values are cached.

    Show solution
    Java
    Integer a = 127, b = 127;
    Integer c = 128, d = 128;
    System.out.println(a == b);
    System.out.println(c == d);
    System.out.println(c.equals(d));

    It prints true, false, true. Autoboxing uses Integer.valueOf, which caches values from −128 to 127, so a and b are the same object. 128 is outside the cache, so c and d are different objects, and == (reference comparison) is false. equals compares values. Always compare wrapper objects with equals.

  14. 14.Why does this loop throw ConcurrentModificationException, and how do you fix it?

    IntermediateDebuggingCollections
    Show hint

    What does the for-each loop use under the hood?

    Show solution
    Java
    for (String name : names) {
        if (name.isBlank()) {
            names.remove(name);   // structural change during iteration
        }
    }

    The for-each loop uses an Iterator. Removing elements through the list (not the iterator) changes it structurally, and the fail-fast iterator detects that on its next step and throws. Fixes:

    Java
    names.removeIf(String::isBlank);              // simplest
    
    Iterator<String> it = names.iterator();       // or remove through the iterator
    while (it.hasNext()) {
        if (it.next().isBlank()) it.remove();
    }
  15. 15.Find the first non-repeating character in a string.

    IntermediateCodingHashing
    Show hint

    Count first, then scan again in the original order.

    Show solution
    Java
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    public class Main {
        static Character firstUnique(String s) {
            Map<Character, Integer> counts = new LinkedHashMap<>();
            for (char c : s.toCharArray()) counts.merge(c, 1, Integer::sum);
            for (Map.Entry<Character, Integer> e : counts.entrySet()) {
                if (e.getValue() == 1) return e.getKey();
            }
            return null;
        }
    
        public static void main(String[] args) {
            System.out.println(firstUnique("swiss"));   // w
            System.out.println(firstUnique("aabb"));    // null
        }
    }

    A LinkedHashMap remembers insertion order, so the second pass finds the first unique character in O(k) after an O(n) count.

  16. 16.Group a list of employees by department and compute the average salary of each, using streams.

    IntermediateCodingStreams
    Show hint

    Collectors.groupingBy takes a downstream collector.

    Show solution
    Java
    import java.util.List;
    import java.util.Map;
    import java.util.TreeMap;
    import java.util.stream.Collectors;
    
    public class Main {
        record Employee(String name, String dept, double salary) {}
    
        public static void main(String[] args) {
            List<Employee> staff = List.of(
                    new Employee("Asha", "Eng", 90000), new Employee("Ravi", "Eng", 70000),
                    new Employee("Meera", "Sales", 60000));
    
            Map<String, Double> avg = staff.stream()
                    .collect(Collectors.groupingBy(Employee::dept, TreeMap::new,
                            Collectors.averagingDouble(Employee::salary)));
            System.out.println(avg);   // {Eng=80000.0, Sales=60000.0}
        }
    }

    groupingBy(classifier, mapFactory, downstream) groups and summarizes in one pass; TreeMap::new keeps departments sorted.

  17. 17.What is the difference between volatile and synchronized?

    AdvancedConceptConcurrency
    Show hint

    Visibility versus atomicity.

    Show solution

    volatile guarantees visibility (a write is seen by other threads' later reads) and prevents certain reorderings, but does not make compound operations atomic: count++ on a volatile field can still lose updates. synchronized provides both mutual exclusion (only one thread in the block per lock) and visibility. Use volatile for simple flags such as a running boolean; use synchronized, locks or AtomicInteger for read-modify-write operations.

  18. 18.How would you implement an LRU cache in Java?

    AdvancedDesignCollections
    Show hint

    Which map can keep entries in access order?

    Show solution

    The quickest correct answer extends LinkedHashMap with access order and overrides removeEldestEntry:

    Java
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    class LRUCache<K, V> extends LinkedHashMap<K, V> {
        private final int capacity;
    
        LRUCache(int capacity) {
            super(16, 0.75f, true);   // true = iterate in access order
            this.capacity = capacity;
        }
    
        @Override
        protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
            return size() > capacity;   // evict the least recently used entry
        }
    }

    get and put are O(1). If asked to build it from scratch, combine a HashMap<K, Node> for O(1) lookup with a doubly linked list that moves accessed nodes to the front and removes from the tail. For concurrent use, wrap access in a lock or use a library cache such as Caffeine.

Review the lessons