build() wraps the builder's own mutable list with List.copyOf so the finished object holds an independent snapshot. Continuing to mutate the builder afterwards has no effect on the object that was already built.
class Team {
private final List<String> members;
private Team(List<String> members) { this.members = members; }
List<String> members() { return members; }
static class Builder {
private final List<String> members = new ArrayList<>();
Builder add(String name) { members.add(name); return this; }
Team build() { return new Team(List.copyOf(members)); }
}
}
Team.Builder builder = new Team.Builder().add("Ana").add("Ben");
Team team = builder.build();
builder.add("Cid");
System.out.println("Team after the builder kept mutating: " + team.members());
Team after the builder kept mutating: [Ana, Ben]
Run this yourself in the Online Java Compiler, spin up a live REST API in the API Sandbox, or practise with Java interview questions.
Published 2026-09-27