← Home
☕Java Developer Interview Questions — Fresher to 5 YOEJava Dev InterviewNEW
🚀

Modern Java (9–21)

Records, sealed classes, pattern matching, virtual threads · 20 questions

1

What does the `var` keyword (Java 10) do, and how is it different from dynamic typing?

Must Know🌱 Fresher

var lets the compiler infer a local variable's type from its initializer — it's purely a compile-time convenience, not dynamic typing. The variable still has a fixed, static type determined once at compile time; you just don't have to spell it out. It only works for local variables with an initializer (not fields, method parameters, or return types), and you can't assign a different-typed value to it later.

var is static typing, just inferredjava
var list = new ArrayList<String>(); // list's type is ArrayList<String>, fixed forever
list.add("ok");
list.add(42);       // compile error -- list is still List<String>, not List<Object>
var x = 5;
x = "hello";        // compile error -- x's type is int, inferred once
Java 10var
2

What are records (Java 14/16), and what boilerplate do they remove?

Must Know🌱 Fresher

A record is a compact syntax for an immutable data carrier — declaring the fields once auto-generates a canonical constructor, private final fields, public accessor methods (named after the field, not getX()), plus equals(), hashCode(), and toString() based on all components.

A record replaces ~40 lines of boilerplatejava
record Point(int x, int y) { }

// generated for free:
// Point(int x, int y) { this.x = x; this.y = y; }
// int x() { return x; }  int y() { return y; }
// equals(), hashCode(), toString() -- all based on x and y
Java 16Records
3

What are sealed classes/interfaces (Java 17), and what problem do they solve?

Must Know📊 Mid

A sealed class/interface (sealed ... permits A, B, C) explicitly restricts which classes are allowed to extend/implement it — anything not listed in permits simply won't compile. Combined with pattern matching in switch, the compiler can then verify exhaustiveness (every permitted subtype is handled) without needing a default branch — giving Java something close to algebraic data types from functional languages.

🔒 Sealed hierarchy — closed set of subtypes
sealed interface Shape permits Circle, Square, Triangle { }

record Circle(double r) implements Shape { }
record Square(double side) implements Shape { }
record Triangle(double base, double h) implements Shape { }

// Any OTHER class trying "implements Shape" -> compile error
// switch over Shape can be exhaustive with no default needed
Java 17Sealed Classes
4

What are switch expressions (Java 14), and how do they differ from switch statements?

Must Know🌱 Fresher

A switch expression (Java 14) produces a value and uses -> arrow syntax — no fall-through between cases (each case is self-contained), and the compiler enforces exhaustiveness for enums/sealed types. A switch statement is the older :/break form — it doesn't produce a value, and forgetting a break silently falls through into the next case, a classic source of bugs.

Switch expressionjava
String size = switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> "6";
    case TUESDAY -> "7";
    default -> {
        yield "unknown"; // yield needed inside a block arm
    }
};
Java 14Switch
5

What are virtual threads (Java 21), in brief?

Must Know📊 Mid

Virtual threads (Java 21, Project Loom) are lightweight, JVM-managed threads — you can spin up millions of them because they're multiplexed onto a small pool of real OS ("carrier") threads, and blocking a virtual thread on I/O just unmounts it from its carrier rather than parking a scarce OS thread. This makes the simple "thread-per-request" blocking style practical again for very high-concurrency I/O-bound services, without needing to rewrite everything in a reactive/async style. See the full Virtual Threads deep dive → for the platform-vs-virtual thread diagram, pinning gotchas, and when they don't help (CPU-bound work sees no benefit).

Java 21Virtual Threads
6

Do records auto-generate equals(), hashCode(), and toString()? How?

Must Know🌱 Fresher

Yes, automatically, based on all of the record's components: two record instances are equals() if they're the same record type and every component is equal; hashCode() combines all components' hash codes; toString() prints the record name and each component's name/value. Any of the three can still be overridden explicitly if you need custom behavior (e.g. excluding a field from equality, or masking a sensitive field in toString()).

record's generated toString()java
record Point(int x, int y) {}
System.out.println(new Point(1, 2)); // "Point[x=1, y=2]"
Records
7

What is pattern matching for instanceof (Java 16)?

Important🌱 Fresher

Before Java 16, an instanceof check required a separate explicit cast to actually use the narrowed type. Pattern matching folds the cast into the check itself, binding a new variable only in scope where the match succeeded:

Before vs afterjava
// Before
if (obj instanceof String) {
    String s = (String) obj; // manual cast
    System.out.println(s.length());
}

// Java 16+
if (obj instanceof String s) { // s is bound and in scope here
    System.out.println(s.length());
}
Java 16Pattern Matching
8

What is pattern matching for switch (Java 21)?

Important📊 Mid

Java 21 lets switch match on the type of the selector, not just constant values — each case can bind a pattern variable, and when clauses add extra guard conditions.

Pattern matching for switchjava
String describe(Object obj) {
    return switch (obj) {
        case Integer i when i < 0 -> "negative int";
        case Integer i -> "int: " + i;
        case String s -> "string of length " + s.length();
        case null -> "it's null";
        default -> "something else";
    };
}
Java 21Pattern MatchingSwitch
9

What are text blocks (Java 15)?

Important🌱 Fresher

Text blocks ("""...""", Java 15) let you write multi-line string literals (SQL, JSON, HTML) without a wall of \n and + concatenation. The compiler strips a common leading-whitespace indentation and normalizes line endings, so the source stays readable and matches how the text visually looks.

Text blockjava
String json = """
    {
      "name": "Ada",
      "role": "Engineer"
    }
    """;
Java 15Text Blocks
10

What are Sequenced Collections (Java 21)?

Important📊 Mid

Before Java 21, there was no common interface for "a collection with a defined encounter order" — List had get(0)/get(size()-1), LinkedHashSet and Deque each had their own ad-hoc ways to get first/last, and none of them agreed on an API. SequencedCollection, SequencedSet, and SequencedMap retrofit a uniform API onto existing ordered types:

Uniform first/last/reversed APIjava
list.getFirst(); list.getLast();
list.addFirst(x); list.addLast(x);
list.reversed(); // a reversed VIEW, no copying

linkedHashSet.getFirst();  // now works uniformly, same API as List
linkedHashMap.reversed();  // same idea for maps
Java 21Collections
11

What does the `yield` keyword do in a switch expression?

Important📊 Mid

Inside a switch expression's block-bodied case (-> { ... }), you can't use a bare return — that would return from the enclosing method, not produce the switch expression's value. yield is the keyword that specifically "returns" a value from that block as the switch expression's result, without exiting the surrounding method.

yield inside a block armjava
int numLetters = switch (day) {
    case MONDAY, FRIDAY -> 6;
    case TUESDAY -> {
        int result = computeSomething();
        yield result; // must use yield, not return, inside this block
    }
};
Switchyield
12

What are record patterns (Java 21), and how do they combine with switch?

Advanced📊 Mid

Record patterns (Java 21) let you destructure a record's components directly inside a pattern match — including nesting, to reach into records-within-records in one match, instead of manually calling accessor methods after the type check.

Destructuring nested records with switchjava
record Point(int x, int y) { }
record Line(Point start, Point end) { }

static String describe(Object obj) {
    return switch (obj) {
        case Line(Point(var x1, var y1), Point(var x2, var y2)) ->
            "line from (%d,%d) to (%d,%d)".formatted(x1, y1, x2, y2);
        default -> "not a line";
    };
}
Java 21Record Patterns
13

When would you use a sealed interface instead of an enum?

Advanced📊 Mid

Use an enum when every variant is a fixed, simple singleton constant with (at most) shared behavior/fields declared once (e.g. DayOfWeek). Use a sealed interface when each variant needs to carry different data/shape — an enum constant can't hold a different set of fields per constant, but a sealed interface's permitted implementations can each be a distinct record with its own components (e.g. modeling an API result as sealed interface Result permits Success, Failure, where Success carries a payload and Failure carries an error message — impossible to express cleanly as one enum).

Sealed ClassesEnum
14

What is the Java Platform Module System (JPMS, Java 9), and what problem does it solve?

Optional📊 Mid

JPMS (module-info.java) lets you group packages into named modules that explicitly declare what they export (public API for other modules) and what they require (dependencies) — enforced by the JVM at both compile and runtime, not just convention. It solves the old "JAR hell" problem: with plain JARs on the classpath, any public class in any JAR is accessible everywhere, and there's no reliable way to declare or enforce inter-library dependencies. In practice, adoption outside the JDK's own modules has been slow — most application code still ships as regular JARs on the classpath rather than fully modularized, so this tends to come up as a "do you know it exists" question more than a "use it daily" one.

Java 9Modules
15

What are "Helpful NullPointerExceptions" (Java 14)?

Optional🌱 Fresher

Since Java 14, a NullPointerException can include a precise description of which reference in a chained expression was null — instead of just a line number, the message spells out the exact variable/method call, which is enormously helpful for a long chain like a.getB().getC().getD() where any of several links could have been null.

Before vs afterjava
// Before: "Exception in thread "main" java.lang.NullPointerException" (which reference?!)
// Java 14+: "Cannot invoke "C.getD()" because the return value of "B.getC()" is null"
Java 14NPE
16

How do records compare to Lombok’s @Data annotation?

Optional📊 Mid

Lombok's @Data is an annotation processor that generates getters, setters, equals/hashCode/toString — but the fields it operates on are still typically mutable (it generates setters by default), and it requires an external build-tool dependency and IDE plugin. A record is a native language feature, generates no setters (records are inherently immutable), needs no extra tooling, and its structure is understood natively by the compiler (enabling record patterns). Records are the better fit for pure immutable data carriers; Lombok remains relevant for mutable JavaBean-style classes (e.g. many JPA entities still expect mutability) where records don't apply.

RecordsLombok
17

Can you use `var` in lambda parameters, and why would you?

Optional🌱 Fresher

Java 11 allowed var in lambda parameter lists, mainly so you could attach annotations to inferred-type lambda parameters (which plain (x, y) -> ... syntax doesn't allow) — e.g. a nullability or validation annotation from a static analysis tool.

var lets you annotate an inferred lambda parameterjava
(@NonNull var x, @NonNull var y) -> x + y;
Java 11varLambda
18

What new String methods did Java 11 add (isBlank, strip, repeat, lines)?

Optional🌱 Fresher
  • isBlank() — true if empty or only whitespace (unlike isEmpty(), which only checks length 0).
  • strip()/stripLeading()/stripTrailing() — Unicode-aware whitespace trimming (better than the older trim(), which only understands ASCII whitespace).
  • repeat(n) — repeat the string n times.
  • lines() — a Stream<String> of the string split by line terminators, handling \n/\r\n uniformly.
Java 11String
19

What is structured concurrency, and what problem is it trying to solve?

Optional📊 Mid

Structured concurrency (an incubating/preview API introduced alongside virtual threads) treats a group of related concurrent subtasks as a single unit of work with one lifetime — if the parent scope is cancelled or errors out, all its child tasks are automatically cancelled with it, and you can't "leak" a forgotten background task the way ad-hoc executor.submit(...) calls scattered through code easily can. It's essentially bringing the same discipline structured programming brought to goto-style control flow, but applied to concurrent tasks instead of sequential jumps.

Structured ConcurrencyVirtual Threads
20

What are Java LTS releases, and why does the version you target matter?

Optional📊 Mid

Oracle's release cadence ships a new Java version every six months, but only marks certain versions (8, 11, 17, 21, ...) as Long-Term Support (LTS) — receiving extended security patches for years. Most enterprises deliberately stay on the latest LTS rather than chasing every six-month release, since non-LTS versions stop receiving updates once the next release ships. This matters practically for interviews too: which version a company runs in production determines which language features (records, sealed classes, virtual threads, pattern matching) are actually available to use day-to-day, not just what you've read about.

Java VersionsLTS