Builder: optional vs required fields
Fast recall
Quick revision
Core answer
build(). Optional fields can have documented defaults or remain absent. The final constructor should still protect the object's invariants so no construction path can create an invalid object.Interview-ready guide
Interview answer
Required versus optional fields are rules I design; the Builder pattern does not enforce them automatically. For a simple object, I might start with Order.builder(customerId) so the required customer is supplied first, then provide fluent methods for optional notes or delivery instructions. If several values must be checked together, build() can reject an invalid combination. A staged builder can enforce steps at compile time, but I use it only when that extra type complexity is justified. Optional values need clear defaults or absence rules. I also keep the final object's invariants at its constructor or factory boundary so another construction path cannot silently create an invalid object.
Builder: optional vs required fields
Direct Answer
The Builder pattern does not automatically know which fields are required. A design can require them in a builder factory or constructor, use staged builder interfaces, or validate them in build(). Optional fields can have documented defaults or remain absent. The final constructor should still protect the object's invariants so no construction path can create an invalid object.
Code Example
public class PaymentRequest {
private final Long userId; // required
private final Double amount; // required
private final String currency; // required
private final String paymentMethod; // optional
private final String billingAddress; // optional
private final boolean saveCard; // optional
private PaymentRequest(Builder builder) {
this.userId = builder.userId;
this.amount = builder.amount;
this.currency = builder.currency;
this.paymentMethod = builder.paymentMethod;
this.billingAddress = builder.billingAddress;
this.saveCard = builder.saveCard;
}
public static class Builder {
// Required fields: final + constructor parameters
private final Long userId;
private final Double amount;
private final String currency;
// Optional fields: mutable + defaults
private String paymentMethod = "CREDIT_CARD";
private String billingAddress;
private boolean saveCard = false;
public Builder(Long userId, Double amount, String currency) {
this.userId = userId;
this.amount = amount;
this.currency = currency;
}
public Builder paymentMethod(String method) {
this.paymentMethod = method;
return this;
}
public Builder billingAddress(String address) {
this.billingAddress = address;
return this;
}
public Builder saveCard(boolean save) {
this.saveCard = save;
return this;
}
public PaymentRequest build() {
if (amount <= 0) {
throw new IllegalStateException("Amount must be positive");
}
if (!List.of("USD", "EUR", "GBP").contains(currency)) {
throw new IllegalStateException("Invalid currency");
}
return new PaymentRequest(this);
}
}
}
Common Mistakes & Pitfalls
- Making everything optional: Freshers often put all fields as optional to avoid complicated constructors, but this allows building incomplete objects that fail later with NullPointerException in unpredictable places.
- Not providing sensible defaults for optionals: Leaving optional fields as null instead of providing safe defaults forces every caller to handle null, spreading validation logic everywhere.
- Forgetting validation in build(): Even with required fields in the constructor, you still need to validate invariants in build() — like checking that an amount is positive or an email contains an at sign.
- Using null for optional primitive wrappers: Making optional numeric fields like discount percentage use Integer instead of int with a default value creates null handling complexity; prefer primitives with zero defaults.
Check your understanding
Answer these without looking back at the article.
- What exception should you throw when required fields are missing in build()?
- How does Lombok's @Builder handle required fields differently?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.