skip to content

Best Practices & Design

Java-specific design knowledge: how SOLID, the GoF patterns and clean-code principles look in idiomatic Java, plus mechanics unique to the language such as the equals/hashCode contract, immutability with final and records, and Effective Java idioms. Interviewers use this area to move from can you code to would I want to maintain your code.

part ofJavaoverview, primer and where to startread it →
on this pageshow

explore

questions

144 · 5 sections

What are the SOLID principles, and how does idiomatic Java let you express each one in code?

level: middleimportance: must knowfreq 78%
basics
~20 s

SOLID is five design rules: each class one job, open to extend but closed to change, subtypes must be substitutable, small interfaces, depend on abstractions not concretes. In Java you use interfaces, abstract classes, and dependency injection to follow them.

open as a page

What do DRY, KISS, YAGNI, and separation of concerns mean, and how do you apply them when writing Java?

level: juniorimportance: should knowfreq 62%
basics
~10 s

DRY: don't repeat the same logic — extract it into one method. KISS: keep it simple. YAGNI: don't build features you don't need yet. Separation of concerns: each class/method does one kind of job.

open as a page

How do classic GoF design patterns show up in the Java standard library? Give concrete JDK examples.

level: middleimportance: should knowfreq 70%
basics
~20 s

The JDK is full of GoF patterns: BufferedInputStream wrapping a stream is Decorator, Comparator passed to sort is Strategy, Calendar.getInstance() is a Factory, Runnable submitted to an executor is Command, and Iterator/Iterable is the Iterator pattern.

open as a page

How have functional interfaces and lambdas reshaped how classic patterns like Strategy are written in modern Java?

level: seniorimportance: should knowfreq 55%
basics
~20 s

A functional interface has one abstract method, so you can pass a lambda where it's expected. That turns patterns like Strategy into a one-line lambda instead of a whole class — e.g. passing a Comparator to sort, or a Runnable to a thread.

open as a page

How do you decide when applying SOLID and GoF patterns adds value versus when it becomes over-engineering in a Java codebase?

level: principalimportance: should knowfreq 40%
basics
~20 s

Patterns and SOLID earn their cost only when there's real, recurring change. If a problem is simple and stable, a plain class or method beats an interface plus a pattern. Add abstraction when a second real case appears, not on speculation.

open as a page

What is the Adapter pattern, and how does it appear in the JDK?

level: juniorimportance: must knowfreq 70%
basics
~20 s

Adapter is a wrapper that lets two incompatible interfaces work together. It takes an object with one interface and exposes it as another. In the JDK, InputStreamReader adapts a byte InputStream into a char Reader.

open as a page

What is the Builder pattern in Java, and what problem does it solve?

level: juniorimportance: must knowfreq 78%
basics
~20 s

Builder is a way to construct an object step by step using chained method calls, then a final build() call. It avoids constructors with lots of confusing parameters, and the result is usually an immutable object.

open as a page

What is the Chain of Responsibility pattern, and how do Servlet Filters embody it?

level: juniorimportance: must knowfreq 70%
basics
~20 s

It is a design pattern where a request passes through a series of handlers, and each one decides whether to process it or pass it along. Servlet Filters are a chain: each filter can act on a request, then call the next one.

open as a page

What is the Command design pattern, and how do Java's Runnable and Callable embody it?

level: juniorimportance: must knowfreq 70%
basics
~20 s

The Command pattern wraps a request as an object so you can pass it around, store it, and run it later. In Java, Runnable and Callable are command objects: each bundles a piece of work in one method (run or call) that something else executes when it chooses.

open as a page

What is the Composite design pattern, and how does Java's AWT/Swing Component/Container hierarchy illustrate it?

level: juniorimportance: must knowfreq 72%
basics
~20 s

Composite lets you treat a single object and a group of objects the same way. In Swing, both a single widget (like a JButton) and a container of widgets (like a JPanel) are Components, so code can handle either through the same Component type.

open as a page

What are the five properties the equals() contract requires (reflexive, symmetric, transitive, consistent, non-null), and what is a common way to violate symmetry/transitivity?

level: middleimportance: must knowfreq 70%
basics
~20 s

equals() must be reflexive (x equals itself), symmetric (if x equals y then y equals x), transitive (if x=y and y=z then x=z), consistent (same result if nothing changes), and return false for null. Mixing a class with its subclass in equals() often breaks symmetry or transitivity.

open as a page

How do Java records implement equals()/hashCode(), and how would you write a correct manual implementation for a non-record value class?

level: middleimportance: should knowfreq 50%
basics
~20 s

A record auto-generates equals() and hashCode() from all its components, so equal field values mean equal objects. For a regular class, compare each significant field with Objects.equals() in equals(), and combine the same fields with Objects.hash() in hashCode().

open as a page

In equals(), when should you use getClass() versus instanceof for the type check, and what are the tradeoffs?

level: seniorimportance: should knowfreq 45%
basics
~20 s

Use instanceof for flexibility — it lets compatible types compare and is null-safe — but only if subclasses don't add fields that affect equality. Use getClass() for strict 'exactly the same class' equality, at the cost that a subclass can never equal its parent.

open as a page

Why is using a mutable object as a HashMap key (or HashSet element) dangerous, and how does this relate to equals()/hashCode()?

level: seniorimportance: should knowfreq 55%
basics
~20 s

A hash collection records an object's hashCode() when you add it. If you then mutate a field used by hashCode(), the object's bucket changes, so the collection looks in the old bucket and can no longer find it. Use immutable keys.

open as a page

What are the main benefits of making a Java class immutable?

level: juniorimportance: must knowfreq 78%
basics
~20 s

An immutable object never changes after it's built. That makes it safe to share between threads with no locking, safe to cache and reuse, and safe to use as a map or set key. It's also easier to reason about because its state can't surprise you.

open as a page

What steps make a Java class immutable? Walk through the checklist.

level: middleimportance: must knowfreq 78%
basics
~20 s

Make the class final so nobody can subclass it, make every field private and final, provide no setters, set all fields once in the constructor, and copy any mutable field when it goes in or comes out so outside code can't change your data.

open as a page

What is defensive copying, and why must it happen on both input and output for a mutable field?

level: middleimportance: must knowfreq 70%
basics
~20 s

Defensive copying means storing and returning copies of mutable objects instead of the originals. You copy in the constructor so the caller can't change your data later, and copy in the getter so the caller can't change the object you hand back. Both are needed because each closes a different leak.

open as a page

Why are immutable objects ideal as keys in a HashMap or HashSet, and what breaks if you use a mutable key?

level: middleimportance: must knowfreq 71%
basics
~20 s

A HashMap finds entries using the key's hashCode. If a key never changes, its hashCode stays the same, so the entry is always findable. If you mutate a key after putting it in, its hashCode can change and the map looks in the wrong bucket - the entry is effectively lost.

open as a page

Why must an immutable class prevent subclassing, and what are the ways to do it?

level: juniorimportance: should knowfreq 48%
basics
~20 s

If a class can be subclassed, a subclass could add changeable fields or override methods to return different values, breaking the promise that the object never changes. You stop this by marking the class final, or by hiding the constructor (making it private) and creating instances through a static factory method.

open as a page

What problem does the Builder pattern solve, and why are telescoping constructors and the JavaBeans setter pattern poor alternatives for a class with many optional parameters?

level: juniorimportance: must knowfreq 78%
basics
~20 s

Builder solves having too many constructor parameters. Telescoping constructors (one per combination) become unreadable and error-prone. JavaBeans setters allow building an object step by step but leave it mutable and possibly half-built. Builder gives readable, named, optional parameters and a finished immutable object.

open as a page

Compare try-with-resources to the old try/finally close pattern. Why is try-with-resources strictly better for managing AutoCloseable resources?

level: juniorimportance: must knowfreq 64%
basics
~20 s

try-with-resources declares the resource in the try header and closes it automatically when the block ends, even on exception — less code and no forgetting. Old try/finally needs a manual close() in finally, is easy to get wrong with multiple resources, and can hide the real exception if close() also throws.

open as a page

What is a raw type in Java, why should you avoid raw types, and what do you lose by using them?

level: juniorimportance: must knowfreq 70%
basics
~20 s

A raw type is a generic class used without its type parameter, like List instead of List<String>. Avoid them because you lose compile-time type checking, so wrong types slip in and blow up at runtime with a ClassCastException.

open as a page

What is a static factory method in Java, and why might you prefer one over a public constructor?

level: juniorimportance: must knowfreq 70%
basics
~20 s

A static factory method is a static method that returns an instance of its class instead of using new directly. You prefer it because it can have a descriptive name, can reuse cached objects, and hides how the object is built.

open as a page

How does the Builder idiom produce an immutable object, and why is calling validation in build() better than validating in individual setter-style methods?

level: middleimportance: must knowfreq 62%
basics
~20 s

The target class has all-final fields and a private constructor that copies values from the builder once, so once built it can't change — that's immutable. Validating in build() means the whole object's invariants are checked together, right before it's created, instead of in isolated method calls.

open as a page