Chaturmind
LearnDSASystem DesignInterview PrepDevOpsEngineering GrowthBlog
Start learning
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML
  • DevOps
  • Engineering Growth
  • Java Interview Prep

Company

  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← Java Interview Prep: 2–5 Years

Revise the Fresher Tier

  • Revise: Core Java Fundamentals (Fresher Tier)
  • Revise: Collections, Threads, Java 8 & Coding (Fresher Tier)
  • Revise: Spring Core, Spring Boot & Spring MVC (Fresher Tier)
  • Revise: Hibernate, SQL, Microservices, Maven & Git (Fresher Tier)

Intermediate Core Java

  • Intermediate OOP & Language Features — Interview Questions
  • Enums, Generics, Pass-by-Value & Imports — Interview Questions
  • Collections Internals & Scenarios — Interview Questions
  • JVM, Memory & Class Loading — Interview Questions
  • Exception Design & Serialization Edge Cases — Interview Questions

Java 8 Deep Dive & Stream Coding

  • Lambdas, Functional Interfaces & Method References — Interview Questions
  • Default Methods, Backward Compatibility & Optional — Interview Questions
  • Stream API Internals (Part 1) — Interview Questions
  • Stream API Internals (Part 2) — Interview Questions
  • Stream Coding Problems (Level 2, Part 1) — Interview Questions
  • Stream Coding Problems (Level 2, Part 2) — Interview Questions

Concurrency & Multithreading

  • Synchronization, Locks & Deadlocks — Interview Questions
  • Executors, ThreadLocal & Concurrent Collections — Interview Questions

Spring Framework In Depth

  • Bean Lifecycle, Contexts & Circular Dependencies — Interview Questions
  • Spring Bean Conflicts, AOP, Batch & Injection Styles — Interview Questions

Spring Boot In Depth & Scenarios

  • Spring Boot Internals & Auto-Configuration — Interview Questions
  • Spring Boot Configuration, Profiles & Secrets — Interview Questions
  • Spring Boot Data, Transactions & Caching — Interview Questions
  • Spring Boot Testing, Error Pages & Deployment — Interview Questions
  • Spring Boot Performance, Scaling & Resilience — Interview Questions
  • Spring Boot Async, Events & Messaging — Interview Questions
  • Spring Boot Security Scenarios — Interview Questions
  • Actuator, AOP, Spring Cloud & Distributed Tracing — Interview Questions
  • External APIs, Files, GraphQL & WebFlux — Interview Questions

Spring Security

  • Spring Security — OAuth2, CORS, CSRF & Access Rules — Interview Questions
  • Spring Security — Passwords, Filter Chain, Sessions & Debugging — Interview Questions

Apache Kafka

  • Kafka Architecture, Topics & ZooKeeper vs KRaft — Interview Questions
  • Kafka Producers, Consumers, Reliability & Streams — Interview Questions
  • Kafka Security, Connect & Core Scenarios — Interview Questions
  • Kafka Production Scenarios — Interview Questions

Git, Maven & Gradle (Level II)

  • Git Workflows, Rebase & Conflict Handling — Interview Questions
  • Git Recovery, Hooks, Tags & Collaboration — Interview Questions
  • Maven Builds, Multi-Module Projects & Dependency Resolution — Interview Questions
  • Maven Profiles, settings.xml, Plugins & Quality Gates — Interview Questions
  • Gradle Fundamentals, Migration & Dependencies — Interview Questions
  • Gradle Performance, Plugins, Testing & Publishing — Interview Questions

Deployment & CI/CD

  • Sessions, CI/CD Pipelines, Rollbacks & Secrets — Interview Questions
  • Migrations, Zero-Downtime Releases, Containers & Monitoring — Interview Questions

JUnit 5 & Mockito

  • JUnit 5 — Interview Questions
  • Mockito Basics — Interview Questions
  • Mockito Advanced & Tricky Questions — Interview Questions
Chaturmind
← Java Interview Prep: 2–5 Years

Revise the Fresher Tier

  • Revise: Core Java Fundamentals (Fresher Tier)
  • Revise: Collections, Threads, Java 8 & Coding (Fresher Tier)
  • Revise: Spring Core, Spring Boot & Spring MVC (Fresher Tier)
  • Revise: Hibernate, SQL, Microservices, Maven & Git (Fresher Tier)

Intermediate Core Java

  • Intermediate OOP & Language Features — Interview Questions
  • Enums, Generics, Pass-by-Value & Imports — Interview Questions
  • Collections Internals & Scenarios — Interview Questions
  • JVM, Memory & Class Loading — Interview Questions
  • Exception Design & Serialization Edge Cases — Interview Questions

Java 8 Deep Dive & Stream Coding

  • Lambdas, Functional Interfaces & Method References — Interview Questions
  • Default Methods, Backward Compatibility & Optional — Interview Questions
  • Stream API Internals (Part 1) — Interview Questions
  • Stream API Internals (Part 2) — Interview Questions
  • Stream Coding Problems (Level 2, Part 1) — Interview Questions
  • Stream Coding Problems (Level 2, Part 2) — Interview Questions

Concurrency & Multithreading

  • Synchronization, Locks & Deadlocks — Interview Questions
  • Executors, ThreadLocal & Concurrent Collections — Interview Questions

Spring Framework In Depth

  • Bean Lifecycle, Contexts & Circular Dependencies — Interview Questions
  • Spring Bean Conflicts, AOP, Batch & Injection Styles — Interview Questions

Spring Boot In Depth & Scenarios

  • Spring Boot Internals & Auto-Configuration — Interview Questions
  • Spring Boot Configuration, Profiles & Secrets — Interview Questions
  • Spring Boot Data, Transactions & Caching — Interview Questions
  • Spring Boot Testing, Error Pages & Deployment — Interview Questions
  • Spring Boot Performance, Scaling & Resilience — Interview Questions
  • Spring Boot Async, Events & Messaging — Interview Questions
  • Spring Boot Security Scenarios — Interview Questions
  • Actuator, AOP, Spring Cloud & Distributed Tracing — Interview Questions
  • External APIs, Files, GraphQL & WebFlux — Interview Questions

Spring Security

  • Spring Security — OAuth2, CORS, CSRF & Access Rules — Interview Questions
  • Spring Security — Passwords, Filter Chain, Sessions & Debugging — Interview Questions

Apache Kafka

  • Kafka Architecture, Topics & ZooKeeper vs KRaft — Interview Questions
  • Kafka Producers, Consumers, Reliability & Streams — Interview Questions
  • Kafka Security, Connect & Core Scenarios — Interview Questions
  • Kafka Production Scenarios — Interview Questions

Git, Maven & Gradle (Level II)

  • Git Workflows, Rebase & Conflict Handling — Interview Questions
  • Git Recovery, Hooks, Tags & Collaboration — Interview Questions
  • Maven Builds, Multi-Module Projects & Dependency Resolution — Interview Questions
  • Maven Profiles, settings.xml, Plugins & Quality Gates — Interview Questions
  • Gradle Fundamentals, Migration & Dependencies — Interview Questions
  • Gradle Performance, Plugins, Testing & Publishing — Interview Questions

Deployment & CI/CD

  • Sessions, CI/CD Pipelines, Rollbacks & Secrets — Interview Questions
  • Migrations, Zero-Downtime Releases, Containers & Monitoring — Interview Questions

JUnit 5 & Mockito

  • JUnit 5 — Interview Questions
  • Mockito Basics — Interview Questions
  • Mockito Advanced & Tricky Questions — Interview Questions
HomeLearnJava Interview PrepJava Interview Prep: 2–5 YearsIntermediate Core Java
✓ FreeIntermediate· 11 min read

Intermediate OOP & Language Features — Interview Questions

Builder vs Factory, final methods, how overload resolution really works, inner/nested/local/anonymous classes (including the Java 16 static-member change), marker interfaces vs annotations, same-named classes, package-private access, final references, and overloading-plus-overriding pitfalls.

Published September 25, 2026


How to use this lesson

At 2–5 years, interviewers expect more than definitions. They want the mechanism (how the compiler picks an overload), the edge cases (static members in inner classes, the hidden reference to the outer instance), and design judgement (a marker interface or an annotation?). Each answer below leads with the short version, then goes deeper.

Q1. What is the Builder pattern, and how is it different from the Factory pattern?

Short answer: Builder constructs a complex object step by step through a fluent API, and then produces the finished, usually immutable, object with build(). It solves the "many optional parameters" problem. Factory hides which concrete class gets created behind a creation method, and returns a ready object in one call.

HttpRequest request = HttpRequest.newBuilder()                // Builder: step by step, readable, immutable result
        .uri(URI.create("https://api.example.com/orders"))
        .timeout(Duration.ofSeconds(5))
        .header("Accept", "application/json")
        .GET()
        .build();

PaymentGateway gateway = PaymentGatewayFactory.forCountry("IN");  // Factory: picks the implementation class
BuilderFactory
ProblemConstructing one complex objectChoosing which object or class to create
StepsMany fluent calls, then build()A single call
Typical outputAn immutable value object with optional fieldsAn implementation of an interface
ValidationIn build(), across all fieldsInside the factory method

Key points to cover:

  • Lombok's @Builder and records with static factories are common in modern code.
  • You can combine the two: a factory that returns a pre-configured builder.

Learn it in depth → Builder Pattern

Q2. What's the impact of declaring a method final on inheritance?

Short answer: A final method can't be overridden, so every subclass inherits exactly that implementation. Use it to protect behaviour that invariants or security depend on. It's typical for template methods, where the overall algorithm is fixed and only certain steps are overridable.

public abstract class PaymentProcessor {
    public final Receipt process(Payment p) {        // the algorithm is locked
        validate(p);
        Receipt r = charge(p);                       // the step subclasses customise
        audit(r);
        return r;
    }
    protected abstract Receipt charge(Payment p);
}

Key points to cover:

  • Overloading a final method, or hiding a method with the same name in a subclass through a different signature, is still possible.
  • Frameworks that create subclass proxies (Spring CGLIB, Hibernate) can't intercept final methods. A @Transactional final method silently loses its transaction.

Q3. Can method overloading be resolved at runtime?

Short answer: No. Choosing an overload is a compile-time decision, based on the static types of the arguments. At runtime, the JVM only performs dynamic dispatch on the receiver object, to pick an override of the method signature that was already chosen.

class Printer {
    void print(Object o) { System.out.println("Object"); }
    void print(String s) { System.out.println("String"); }
}
Object value = "hello";
new Printer().print(value);          // "Object": the compiler only knows the static type Object

Key points to cover:

  • If you need a choice based on runtime type, use polymorphism (move print into the types), pattern matching (switch (value) { case String s -> … }), or the Visitor pattern (double dispatch).

Learn it in depth → Visitor Pattern

Q4. How does Java resolve a call to an overloaded method?

Short answer: The compiler:

  1. Collects the accessible methods with that name.
  2. Keeps the ones applicable to the arguments, in three phases:
    1. no boxing and no varargs (only primitive widening and subtyping);
    2. boxing and unboxing allowed;
    3. varargs allowed.
  3. Stops at the first phase that finds any match, and picks the most specific method. If no single method is most specific, the call is ambiguous, and it's a compile error.
void f(long x)    { }   // phase 1 (widening)
void f(Integer x) { }   // phase 2 (boxing)
void f(int... x)  { }   // phase 3 (varargs)
f(5);                   // → f(long)

void g(Integer a, long b) { }
void g(long a, Integer b) { }
// g(1, 2);             // ambiguous: each needs boxing for one argument → compile error

Q5. How does Java determine which method to call when methods are overloaded? (A common rephrasing)

Short answer: The same compile-time process: match on the method name and the number, types and order of the arguments' static types, applying the three phases above and then choosing the most specific signature. The return type plays no part. Once the signature is fixed, runtime dispatch only selects which class's version of that exact signature runs.

Common trap: assuming null can always be passed. f(null), with overloads f(String) and f(StringBuilder), is ambiguous. With f(Object) and f(String), it picks f(String), because String is more specific than Object.

Q6. Explain inner classes in Java.

Short answer: Java has four kinds of nested class:

  • Static nested class: belongs to the outer class, and has no reference to an outer instance. Use it for builders and helper types.
  • Inner (non-static) class: every instance holds a hidden reference to an outer instance, and can use its private members.
  • Local class: declared inside a method, and can capture effectively final locals.
  • Anonymous class: unnamed, declared and instantiated in a single expression.
public class Order {
    private final List<Line> lines = new ArrayList<>();

    public static final class Builder { … }                  // static nested: no outer instance

    public class LineIterator implements Iterator<Line> {     // inner: uses Order.this.lines
        private int i;
        public boolean hasNext() { return i < lines.size(); }
        public Line next() { return lines.get(i++); }
    }
}
Order.LineIterator it = order.new LineIterator();             // an inner class needs an outer instance

Common trap: using a non-static inner class when you don't need the outer instance. Each inner object keeps its outer object alive, which is a classic memory leak (for example, listeners or tasks outliving their owner). Default to static nested classes.

Q7. Can inner classes declare static members?

Short answer: Since Java 16, yes. JEP 395 (which finalised records) relaxed the rule, so inner classes can now declare static fields, methods and nested types. Before Java 16, a non-static inner class could only declare static final compile-time constants. Static nested classes have always allowed any static members.

class Outer {
    class Inner {
        static int created = 0;          // compiles on Java 16+, a compile error on Java 8–15
        Inner() { created++; }
    }
}

Common trap: repeating the old rule ("inner classes can't have static members") as current fact. It's worth mentioning which Java version your team uses.

Q8. What's the significance of an anonymous inner class?

Short answer: It lets you implement an interface, or extend a class, inline, for one-off use, with no named class. It's handy for callbacks and small strategies. Since Java 8, lambdas replace anonymous classes for functional interfaces. Anonymous classes remain useful when you need state (fields), several methods, or to extend an abstract class.

TimerTask cleanup = new TimerTask() {          // an abstract class: a lambda can't do this
    private int runs;
    @Override public void run() { runs++; purgeExpiredSessions(); }
};

Key points to cover:

  • Differences from lambdas:
    • In an anonymous class, this is the anonymous object. In a lambda, this is the enclosing instance.
    • Anonymous classes create a separate .class file. Lambdas use invokedynamic.
    • Anonymous classes can shadow variables.

Q9. What is a marker interface?

Short answer: An interface with no methods, which marks a class as having some capability or permission. Code checks for it with instanceof, or with the type system. JDK examples: Serializable, Cloneable, RandomAccess, Remote.

Key points to cover:

  • Marker interface vs annotation:
    • A marker interface defines a type, so the compiler can enforce it (void send(Transmittable t)). It's also inherited by subclasses.
    • Annotations carry attributes and can mark methods and fields, but they're only checked at runtime (by reflection) or by annotation processors.
  • Effective Java advice: use a marker interface when you want a type that methods can require. Otherwise, use an annotation.

Q10. When would creating a custom marker interface be useful?

Short answer: When you want the compiler to enforce that only certain classes can be used somewhere. For example, only Auditable entities may be passed to an audit writer, or only Transmittable objects may be sent outside the network boundary.

public interface Transmittable { }                    // marker

public final class ExternalGateway {
    public void send(Transmittable payload) { … }     // non-transmittable objects are rejected at COMPILE time
}
record OrderSummary(String id, BigDecimal total) implements Transmittable { }

Key points to cover:

  • Compare with an instanceof check at runtime, which fails later and less clearly. The type-based approach is the main advantage of a marker interface over an annotation.
  • In modern Java, a sealed interface can go further, and restrict which classes may be marked.

Q11. What happens if two packages have a class with the same name?

Short answer: Nothing breaks. The fully qualified names differ (java.util.Date and java.sql.Date). In a file that uses both, import one, and refer to the other by its fully qualified name. Importing both with single-type imports is a compile error.

import java.util.Date;

class Report {
    Date created;                    // java.util.Date
    java.sql.Date reportingDay;      // fully qualified
}

Key points to cover:

  • On the classpath, two JARs containing the same fully qualified class is a real problem: whichever loads first wins ("JAR hell"). The module system (split-package detection) and tools like Maven Enforcer (banDuplicateClasses) catch it.

Q12. How can you access a package-private class from another package?

Short answer: You can't, through normal code. That's the point of package-private access. The proper options:

  • Make it public, if it really is part of the API.
  • Expose its behaviour through a public interface or facade in the same package (the usual design).
  • For tests, put the test in the same package (in src/test/java).

Reflection with setAccessible(true) technically works for classpath code, but the module system blocks it unless the package is opens. Don't use it in production code.

Q13. Can you modify an object referenced by a final variable?

Short answer: Yes. final fixes the reference, not the object. You can't reassign the variable, but you can call mutating methods on the object it points to.

final List<String> tags = new ArrayList<>();
tags.add("java");                   // ✅ the object changes
// tags = new ArrayList<>();        // ❌ compile error: the reference is final
final List<String> fixed = List.of("a", "b");
// fixed.add("c");                  // UnsupportedOperationException: immutability comes from the object, not 'final'

Q14. What is the default access level if no modifier is given?

Short answer: Package-private: visible only to classes in the same package. It's more restrictive than protected (which adds subclasses in other packages), and less restrictive than private.

Key points to cover:

  • Interface members are the exception: they're implicitly public, and interface fields are public static final.
  • Package-private is a good default for implementation classes, because it keeps the public API small.

Q15. What problems can arise when overloading and overriding are mixed in one hierarchy?

Short answer: The overload is chosen at compile time, from the static type, but the override is chosen at runtime, from the object. When a subclass overloads where you meant it to override, calls through a parent reference silently skip the subclass method.

class Animal { void greet(Animal other) { System.out.println("animal greets animal"); } }
class Dog extends Animal {
    void greet(Dog other) { System.out.println("dog greets dog"); }   // OVERLOAD, not override
}
Animal a = new Dog();
a.greet(new Dog());      // "animal greets animal": greet(Animal) was chosen at compile time; Dog didn't override it

Key points to cover:

  • Prevention:
    • Always use @Override, so the compiler rejects accidental overloads.
    • Avoid overloads that differ only in related parameter types.
    • Prefer distinct method names.
  • The classic real-world example is equals(Money other) instead of equals(Object o).

Follow-up questions this topic invites — and their answers

Q: Why should static nested classes be preferred over inner classes by default? A: They don't capture the outer instance, so they're lighter, can't leak the outer object, and can be instantiated without one. Use an inner class only when it genuinely needs the outer instance's state.

Q: How does an inner class access the outer class's private fields? A: Since Java 11, the JVM supports nestmates. Nested classes are allowed to access each other's private members directly. Before that, the compiler generated synthetic accessor methods.

Q: Can an anonymous class have a constructor? A: Not an explicit one, because it has no name. Use an instance initialiser block, or pass arguments to the superclass constructor: new Base(arg) { … }.

Q: Why do Spring proxies ignore final and private methods? A: CGLIB proxies are subclasses. A subclass can't override final or private methods, so the proxy can't add transactional or caching behaviour around them.

Previous

Revise: Hibernate, SQL, Microservices, Maven & Git (Fresher Tier)

Next

Enums, Generics, Pass-by-Value & Imports — Interview Questions

AI Tutor

Lesson: Intermediate OOP & Language Features — Interview Questions

Quick actions

AI responses can be inaccurate. Verify critical information.