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 pageshowhide
explore
- Design in Java5 questions
- Design Patterns in the JDK105 questions
- Singleton in Java4 questions
- Factory Method in Java5 questions
- Abstract Factory in Java5 questions
- Builder in Java5 questions
- Prototype in Java4 questions
- Adapter in Java5 questions
- Decorator in Java5 questions
- Proxy in Java4 questions
- Facade in Java4 questions
- Composite in Java5 questions
- Bridge in Java5 questions
- Flyweight in Java5 questions
- Observer in Java5 questions
- Strategy in Java4 questions
- Template Method in Java5 questions
- Iterator in Java5 questions
- Command in Java5 questions
- State in Java5 questions
- Chain of Responsibility in Java5 questions
- Visitor in Java5 questions
- Mediator in Java5 questions
- Memento in Java5 questions
- equals() & hashCode()5 questions
- Immutability10 questions
- Building Immutable Classes5 questions
- Immutability Benefits & Trade-offs5 questions
- Effective Java Idioms19 questions
- Static Factory Methods5 questions
- Builder for Many Parameters4 questions
- Favor Generics & Type Safety5 questions
questions
144 · 5 sectionsWhat are the SOLID principles, and how does idiomatic Java let you express each one in code?
basics
~20 sSOLID 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.
What do DRY, KISS, YAGNI, and separation of concerns mean, and how do you apply them when writing Java?
basics
~10 sDRY: 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.
How do classic GoF design patterns show up in the Java standard library? Give concrete JDK examples.
basics
~20 sThe 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.
How have functional interfaces and lambdas reshaped how classic patterns like Strategy are written in modern Java?
basics
~20 sA 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.
How do you decide when applying SOLID and GoF patterns adds value versus when it becomes over-engineering in a Java codebase?
basics
~20 sPatterns 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.
What is the Adapter pattern, and how does it appear in the JDK?
basics
~20 sAdapter 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.
What is the Builder pattern in Java, and what problem does it solve?
basics
~20 sBuilder 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.
What is the Chain of Responsibility pattern, and how do Servlet Filters embody it?
basics
~20 sIt 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.
What is the Command design pattern, and how do Java's Runnable and Callable embody it?
basics
~20 sThe 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.
What is the Composite design pattern, and how does Java's AWT/Swing Component/Container hierarchy illustrate it?
basics
~20 sComposite 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.
What is the relationship between equals() and hashCode() in Java, and why must they be overridden together?
basics
~10 sIf two objects are equal by equals(), they must return the same hashCode(). So whenever you override equals(), you must also override hashCode(), or hash-based collections like HashMap and HashSet will misbehave.
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?
basics
~20 sequals() 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.
How do Java records implement equals()/hashCode(), and how would you write a correct manual implementation for a non-record value class?
basics
~20 sA 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().
In equals(), when should you use getClass() versus instanceof for the type check, and what are the tradeoffs?
basics
~20 sUse 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.
Why is using a mutable object as a HashMap key (or HashSet element) dangerous, and how does this relate to equals()/hashCode()?
basics
~20 sA 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.
What are the main benefits of making a Java class immutable?
basics
~20 sAn 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.
What steps make a Java class immutable? Walk through the checklist.
basics
~20 sMake 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.
What is defensive copying, and why must it happen on both input and output for a mutable field?
basics
~20 sDefensive 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.
Why are immutable objects ideal as keys in a HashMap or HashSet, and what breaks if you use a mutable key?
basics
~20 sA 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.
Why must an immutable class prevent subclassing, and what are the ways to do it?
basics
~20 sIf 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.
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?
basics
~20 sBuilder 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.
Compare try-with-resources to the old try/finally close pattern. Why is try-with-resources strictly better for managing AutoCloseable resources?
basics
~20 stry-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.
What is a raw type in Java, why should you avoid raw types, and what do you lose by using them?
basics
~20 sA 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.
What is a static factory method in Java, and why might you prefer one over a public constructor?
basics
~20 sA 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.
How does the Builder idiom produce an immutable object, and why is calling validation in build() better than validating in individual setter-style methods?
basics
~20 sThe 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.