1.What is the difference between an abstract class and an interface in Java?
easyHow to approach thisAbstract classes can have constructors, instance fields, and both abstract and concrete methods. Interfaces (since Java 8+) can have default and static methods but not constructors or mutable instance state. A class can implement multiple interfaces but extend only one abstract class. Use interfaces for contracts, abstract classes for shared implementation.
2.Explain how garbage collection works in the JVM.
hardHow to approach thisThe JVM's GC automatically reclaims memory from objects with no references. It divides the heap into generations: Young (Eden + Survivor spaces) for short-lived objects and Old for long-lived ones. Minor GC collects Young gen frequently; Major GC collects Old gen less often. Modern collectors (G1, ZGC, Shenandoah) aim for low-pause-time collection. Tune GC based on your latency and throughput requirements.
3.What is the difference between HashMap and ConcurrentHashMap?
mediumHow to approach thisHashMap is not thread-safe; concurrent modifications can cause infinite loops or data corruption. ConcurrentHashMap uses fine-grained locking (segment/node-level) to allow concurrent reads and writes safely. Use HashMap for single-threaded code; use ConcurrentHashMap when multiple threads access the map. Collections.synchronizedMap is an alternative but locks the entire map on every operation.
4.Explain the Java Memory Model and the happens-before relationship.
hardHow to approach thisThe JMM defines how threads interact through memory. Without synchronization, threads may see stale values due to CPU caches and reordering. The happens-before relationship guarantees that memory writes by one thread are visible to another. Established by: synchronized blocks, volatile writes/reads, Thread.start()/join(), and other concurrency primitives.
5.What are generics in Java, and what is type erasure?
mediumHow to approach thisGenerics provide compile-time type safety for collections and classes (List<String> instead of raw List). Type erasure means generic type information is removed at runtime (List<String> becomes List at the bytecode level). This is why you cannot do new T() or instanceof List<String>. Understand bounded wildcards: <? extends T> for reading, <? super T> for writing (PECS principle).
6.What is the difference between checked and unchecked exceptions?
easyHow to approach thisChecked exceptions (IOException, SQLException) must be caught or declared in the method signature. Unchecked exceptions (RuntimeException subclasses: NullPointerException, IllegalArgumentException) do not. Use checked exceptions for recoverable conditions the caller should handle. Use unchecked exceptions for programming errors. Modern Java style favors unchecked exceptions for most cases.
7.How does the Stream API work, and what are its benefits?
mediumHow to approach thisStreams process collections declaratively using operations like filter, map, reduce, and collect. They can be lazy (intermediate operations build a pipeline, terminal operations execute it), parallel (parallelStream()), and composable. Benefits: more readable code, easier parallelization, and no mutation of the source collection. Avoid stateful operations in parallel streams.
8.Explain the volatile keyword and when to use it.
mediumHow to approach thisvolatile ensures that reads and writes to a variable are directly from/to main memory (not CPU cache), and establishes a happens-before relationship. Use it for simple flags (boolean running) where one thread writes and others read. It does NOT make compound operations (check-then-act, increment) atomic. For those, use AtomicInteger or synchronized.
9.What is dependency injection, and how does Spring implement it?
mediumHow to approach thisDI is a design pattern where an object's dependencies are provided externally rather than created internally. This enables: testability (inject mocks), loose coupling, and configuration flexibility. Spring uses annotations (@Autowired, @Component, @Service) and a container (ApplicationContext) to manage object creation and wiring. Constructor injection is preferred over field injection.
10.What is the difference between String, StringBuilder, and StringBuffer?
easyHow to approach thisString is immutable (every modification creates a new object). StringBuilder is mutable and not thread-safe (fast for single-threaded string building). StringBuffer is mutable and thread-safe (synchronized, slower). Use String for most cases, StringBuilder for loops that build strings, and StringBuffer only when multiple threads modify the same builder (rare).
11.How do you prevent a class from being subclassed in Java?
easyHow to approach thisMark the class as final. This prevents inheritance. Common examples: String, Integer, and other wrapper classes are final. Use final classes when: the class invariants could be broken by subclassing, or when you want to guarantee immutability. Alternatively, make the constructor private and provide a static factory method.
12.Explain the equals() and hashCode() contract. What happens if you violate it?
mediumHow to approach thisThe contract: if two objects are equal (equals returns true), they must have the same hashCode. If hashCode is equal, equals may or may not be true. Violating this breaks HashMap and HashSet: you can put an object in a map but fail to find it because get() checks hashCode first. Always override both together. Use Objects.hash() for consistent hashCode implementation.