← Back to DevBytes

Top 50 Java Interview Questions for Mid-Level Developers

Top 50 Java Interview Questions for Mid-Level Developers

Preparing for a mid-level Java developer interview requires more than surface-level knowledge. Interviewers expect you to understand not just the "what" but the "why" and "how" behind Java's core features. This tutorial walks through 50 essential questions, complete with practical code examples, explanations, and best practices to help you stand out.

Why This Matters

Mid-level developers (typically 2–5 years of experience) are expected to write clean, efficient, and maintainable code. You should understand Java's internals, the Collections framework, concurrency, JVM behavior, and modern Java features introduced in versions 8 through 21. Mastering these topics demonstrates readiness for production-grade responsibilities.

Section 1: Core Java Fundamentals

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

JVM (Java Virtual Machine) executes bytecode. JRE (Java Runtime Environment) provides the runtime needed to run Java applications, including the JVM and core libraries. JDK (Java Development Kit) includes the JRE plus development tools like the compiler (javac) and debugger.

2. Is Java purely object-oriented?

No. Java is mostly object-oriented but supports primitive types (int, boolean, char, etc.) and static members, which are not objects. Everything else revolves around classes and objects.

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

== compares references (memory addresses) for objects, while .equals() compares content if overridden.

String a = new String("hello");
String b = new String("hello");
System.out.println(a == b);       // false
System.out.println(a.equals(b));  // true

4. Why is String immutable in Java?

Strings are immutable for security (used in class loading, network connections), thread-safety, and performance (string pool reuse). Once created, a String's value cannot change; operations create new String objects.

5. What is the String pool?

The String pool is a special memory region in the heap where string literals are stored. It allows reuse of identical string values to save memory.

String s1 = "java";
String s2 = "java";
String s3 = new String("java");
System.out.println(s1 == s2);           // true
System.out.println(s1 == s3.intern());  // true

6. What is the difference between String, StringBuilder, and StringBuffer?

7. What are wrapper classes and why use them?

Wrapper classes (Integer, Double, Boolean) convert primitives into objects. They're required for Collections, generics, and provide utility methods like Integer.parseInt().

8. What is autoboxing and unboxing?

Integer i = 10;   // autoboxing: int -> Integer
int j = i;        // unboxing: Integer -> int

9. What is the difference between final, finally, and finalize?

10. What is the difference between static and instance methods?

Static methods belong to the class and can be called without an instance. Instance methods require an object and can access instance variables.

Section 2: Object-Oriented Programming

11. What are the four pillars of OOP?

12. What is the difference between abstract classes and interfaces?

Abstract classes can have constructors, instance variables, and method implementations. Interfaces (pre-Java 8) could only have abstract methods. Since Java 8, interfaces support default and static methods; Java 9 added private methods.

interface Vehicle {
    void start();
    default void honk() {
        System.out.println("Beep!");
    }
}

abstract class Car implements Vehicle {
    abstract int getWheels();
}

13. Can a class extend multiple classes in Java?

No, Java does not support multiple inheritance with classes to avoid the diamond problem. However, a class can implement multiple interfaces.

14. What is method overloading vs overriding?

Overloading happens at compile time within the same class with different parameter lists. Overriding happens at runtime when a subclass provides a specific implementation of a parent method.

// Overloading
class Calculator {
    int add(int a, int b) { return a + b; }
    double add(double a, double b) { return a + b; }
}

// Overriding
class Animal {
    void sound() { System.out.println("Some sound"); }
}
class Dog extends Animal {
    @Override
    void sound() { System.out.println("Bark"); }
}

15. What is the @Override annotation and why use it?

It tells the compiler that a method is intended to override a superclass method. It catches typos and signature mismatches at compile time.

16. What is covariant return type?

An overriding method can return a subtype of the parent method's return type.

class Parent {
    Parent create() { return new Parent(); }
}
class Child extends Parent {
    @Override
    Child create() { return new Child(); }
}

17. Can you override a static method?

No. Static methods are bound at compile time (static binding). Redefining a static method in a subclass is called method hiding, not overriding.

18. What is the super keyword used for?

super refers to the parent class. It's used to call parent constructors, access parent fields, and invoke parent methods.

19. What is composition and why prefer it over inheritance?

Composition means having objects as fields rather than extending classes. It promotes loose coupling and follows the "favor composition over inheritance" principle.

class Engine {
    void start() { System.out.println("Engine starts"); }
}
class Car {
    private Engine engine = new Engine();
    void start() { engine.start(); }
}

20. What is the instanceof operator?

It checks if an object is an instance of a class or implements an interface. Java 16 introduced pattern matching for instanceof.

if (obj instanceof String s) {
    System.out.println(s.length());
}

Section 3: Collections Framework

21. What is the Java Collections Framework?

A unified architecture for storing and manipulating groups of objects. It includes interfaces (List, Set, Map, Queue) and implementations (ArrayList, HashSet, HashMap, etc.).

22. What is the difference between ArrayList and LinkedList?

23. What is the difference between HashMap and HashTable?

HashMap is not synchronized and allows one null key and multiple null values. HashTable is synchronized and does not allow nulls. Prefer ConcurrentHashMap for thread-safe maps.

24. How does HashMap work internally?

HashMap uses an array of buckets. The key's hashCode() determines the bucket index. From Java 8, if a bucket has more than 8 entries, it converts the linked list to a balanced tree for O(log n) performance.

25. Why is it important to override hashCode() when overriding equals()?

If two objects are equal via equals(), they must have the same hashCode(). Otherwise, they may end up in different buckets in hash-based collections, breaking their behavior.

class Person {
    String name;
    Person(String name) { this.name = name; }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Person p)) return false;
        return name.equals(p.name);
    }

    @Override
    public int hashCode() {
        return name == null ? 0 : name.hashCode();
    }
}

26. What is the difference between Set and List?

List allows duplicates and maintains insertion order. Set does not allow duplicates and (for HashSet) does not guarantee order.

27. What is TreeMap and how does it differ from HashMap?

TreeMap stores entries sorted by keys using a Red-Black tree. Operations are O(log n). HashMap offers O(1) average operations but no ordering.

28. What is ConcurrentHashMap?

A thread-safe HashMap that uses segment-level locking (or node-level locking in Java 8+). It allows concurrent reads and limited concurrent writes, offering better performance than HashTable.

29. What is the difference between fail-fast and fail-safe iterators?

Fail-fast iterators (e.g., ArrayList's) throw ConcurrentModificationException if the collection is modified during iteration. Fail-safe iterators (e.g., CopyOnWriteArrayList's) work on a copy and don't throw exceptions.

30. How do you sort a collection in Java?

List<Integer> nums = Arrays.asList(5, 2, 8, 1);
Collections.sort(nums);                          // natural order
nums.sort((a, b) -> b - a);                      // descending
nums.sort(Comparator.reverseOrder());            // descending

Section 4: Concurrency and Multithreading

31. What is the difference between a process and a thread?

A process is an independent program with its own memory space. A thread is a lightweight unit within a process that shares memory with other threads.

32. How do you create a thread in Java?

// Approach 1: Extend Thread
class MyThread extends Thread {
    public void run() { System.out.println("Running"); }
}
new MyThread().start();

// Approach 2: Implement Runnable
Thread t = new Thread(() -> System.out.println("Running"));
t.start();

33. What is the difference between Runnable and Callable?

Runnable's run() returns void and cannot throw checked exceptions. Callable's call() returns a value and can throw checked exceptions.

34. What is a Future and CompletableFuture?

Future represents the result of an asynchronous computation. CompletableFuture (Java 8) extends Future with chaining, composition, and callback support.

CompletableFuture.supplyAsync(() -> "Hello")
    .thenApply(s -> s + " World")
    .thenAccept(System.out::println);  // prints "Hello World"

35. What is the difference between synchronized and Lock?

synchronized is a keyword providing implicit lock release. Lock (e.g., ReentrantLock) is an interface offering tryLock, fairness, and interruptible locking, but requires explicit unlock() in a finally block.

36. What is a deadlock and how do you prevent it?

A deadlock occurs when two or more threads wait on each other's locks indefinitely. Prevent it by acquiring locks in a consistent order, using timeouts, or avoiding nested locks.

37. What is the volatile keyword?

volatile ensures a variable's value is always read from main memory, not a thread's cache. It guarantees visibility but not atomicity.

38. What is AtomicInteger and why use it?

It provides atomic operations like incrementAndGet() using CAS (Compare-And-Swap), avoiding synchronization overhead for counters.

AtomicInteger counter = new AtomicInteger(0);
counter.incrementAndGet();
counter.compareAndSet(1, 5);

39. What is the ExecutorService framework?

It manages a pool of threads and provides methods to submit tasks. It decouples task submission from execution policy.

ExecutorService executor = Executors.newFixedThreadPool(4);
executor.submit(() -> System.out.println("Task"));
executor.shutdown();

40. What is ThreadLocal?

ThreadLocal provides thread-local variables, where each thread has its own independently initialized copy. Useful for per-thread state like database connections or formatters.

Section 5: Exception Handling

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

Checked exceptions (e.g., IOException) are checked at compile time and must be caught or declared. Unchecked exceptions (e.g., NullPointerException) extend RuntimeException and are not enforced at compile time.

42. What is the try-with-resources statement?

It automatically closes resources that implement AutoCloseable, eliminating the need for explicit finally blocks.

try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
    System.out.println(br.readLine());
} catch (IOException e) {
    e.printStackTrace();
}

43. Can a finally block be skipped?

Yes, if System.exit() is called in try/catch, or if the JVM crashes, or if the thread is killed.

44. What is a custom exception and how do you create one?

class InvalidUserException extends RuntimeException {
    public InvalidUserException(String message) {
        super(message);
    }
}

throw new InvalidUserException("User not found");

45. What is exception chaining?

Wrapping one exception inside another to preserve the original cause while throwing a higher-level exception.

try {
    // some IO operation
} catch (IOException e) {
    throw new ServiceException("Failed to load data", e);
}

Section 6: Java 8+ Features

46. What are functional interfaces?

Interfaces with exactly one abstract method. They can be used with lambda expressions. Examples: Runnable, Comparator, Predicate, Function, Consumer, Supplier.

@FunctionalInterface
interface MathOperation {
    int operate(int a, int b);
}
MathOperation add = (a, b) -> a + b;
System.out.println(add.operate(3, 4));  // 7

47. What are the core Stream operations?

Streams support declarative operations on collections. Intermediate operations (filter, map, sorted) are lazy; terminal operations (collect, forEach, reduce) trigger execution.

List<String> names = List.of("Alice", "Bob", "Charlie", "Anna");
List<String> filtered = names.stream()
    .filter(n -> n.startsWith("A"))
    .map(String::toUpperCase)
    .sorted()
    .collect(Collectors.toList());
// [ALICE, ANNA]

48. What is Optional and why use it?

Optional is a container that may or may not hold a value. It forces explicit handling of null cases and reduces NullPointerException risk.

Optional<String> name = Optional.ofNullable(getName());
String result = name.orElse("Default");
name.ifPresent(System.out::println);

49. What are default and static methods in interfaces?

Default methods provide a default implementation that implementing classes can override. Static methods belong to the interface itself and cannot be overridden.

interface Repository<T> {
    void save(T item);

    default void saveAll(List<T> items) {
        items.forEach(this::save);
    }

    static <U> Repository<U> empty() {
        return item -> { };
    }
}

50. What are records and sealed classes (Java 14+/17)?

Records are concise immutable data carriers. Sealed classes restrict which classes can extend or implement them.

public record Point(int x, int y) {}

public sealed interface Shape permits Circle, Square {}
public record Circle(double radius) implements Shape {}
public record Square(double side) implements Shape {}

Best Practices for Mid-Level Java Developers

Write Clean and Maintainable Code

Use Modern Java Features

Handle Exceptions Thoughtfully

Be Mindful of Concurrency

Optimize Collections Usage

Conclusion

Mastering these 50 Java interview questions gives you a solid foundation for mid-level developer roles. The key is not just memorizing answers but understanding the underlying concepts, trade-offs, and real-world implications. Practice writing code for each topic, build small projects that exercise these features, and review your own code critically. Interviewers value developers who can explain their reasoning, recognize when to apply specific patterns, and demonstrate awareness of performance and maintainability concerns. Combine this knowledge with hands-on experience, and you'll be well-prepared to tackle any mid-level Java interview with confidence.

— Ad —

Google AdSense will appear here after approval

← Back to all articles