Your setter has void setName(String name). Inside, which name is which? The this keyword refers to the current object, letting you write this.name = name to distinguish the field from the parameter.

Disambiguate fields from parameters

Use this.field when names conflict.

Disambiguate.java
Replay: real traced execution (multi-file project)
public class Disambiguate {
    public static void main(String[] args) {
        System.out.println("=== Disambiguating with 'this' ===\n");

        // Without 'this', names would shadow fields
        Person person = new Person("Alice", 30);
        System.out.println("Name: " + person.getName());
        System.out.println("Age: " + person.getAge());

        // Update using setters
        person.setName("Bob");
        person.setAge(25);
        System.out.println("\nAfter update:");
        System.out.println("Name: " + person.getName());
        System.out.println("Age: " + person.getAge());

        System.out.println("\n=== Why Same Names? ===");
        System.out.println("✓ Clear what the parameter represents");
        System.out.println("✓ No need to invent different names");
        System.out.println("✓ Common convention in Java");
    }
}

class Person {
    private String name;
    private int age;

    // Parameters have same name as fields
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Getter - no disambiguation needed
    public String getName() {
        return name;  // Just 'name' is fine here
    }

    public int getAge() {
        return age;
    }

    // Setter - needs 'this' to disambiguate
    public void setName(String name) {
        this.name = name;  // this.name = field, name = parameter
    }

    public void setAge(int age) {
        this.age = age;
    }
}
  1. public static void main(String[] args)

    1public class Disambiguate {2    public static void main(String[] args) {3        System.out.println("=== Disambiguating with 'this' ===\n");4        5        // Without 'this', names would shadow fields  //?problem6        Person person = new Person("Alice", 30);7        System.out.println("Name: " + person.getName());
    output=== Disambiguating with 'this' ===
  2. this.name ← Alice, this.age ← 30, person ← ⟨Person A⟩

    5        // Without 'this', names would shadow fields  //?problem6        Person person→ ⟨Person A⟩ = new Person("Alice", 30);7        System.out.println("Name: " + person.getName());8        System.out.println("Age: " + person.getAge());9        10        // Update using setters11        person.setName("Bob");  //?update12        person.setAge(25);13        System.out.println("\nAfter update:");14        System.out.println("Name: " + person.getName());15        System.out.println("Age: " + person.getAge());16        17        System.out.println("\n=== Why Same Names? ===");18        System.out.println("✓ Clear what the parameter represents");19        System.out.println("✓ No need to invent different names");20        System.out.println("✓ Common convention in Java");21    }22}2324class Person {25    private String name;  //?fields26    private int age;27    28    // Parameters have same name as fields  //?constructor29    Person(String nameAlice, int age30) {30        this.name→ Alice = nameAlice;  //?thisname31        this.age→ 30 = age30;32    }
  3. public String getName()

    pass 1 of 2
    34// Getter - no disambiguation needed  //?getter35public String getName() {36    return nameAlice;  // Just 'name' is fine here37}
  4. System.out.println("Name: " + person.getName());

    6Person person = new Person("Alice", 30);7System.out.println("Name: " + person.getName());8System.out.println("Age: " + person.getAge());
    outputName: Alice
  5. public int getAge()

    pass 1 of 2
    39public int getAge() {40    return age30;41}
  6. System.out.println("Age: " + person.getAge());

    7System.out.println("Name: " + person.getName());8System.out.println("Age: " + person.getAge());910// Update using setters11person.setName("Bob");  //?update12person.setAge(25);
    outputAge: 30
  7. this.name ← Bob

    10        // Update using setters11        person.setName("Bob");  //?update12        person.setAge(25);13        System.out.println("\nAfter update:");14        System.out.println("Name: " + person.getName());15        System.out.println("Age: " + person.getAge());16        17        System.out.println("\n=== Why Same Names? ===");18        System.out.println("✓ Clear what the parameter represents");19        System.out.println("✓ No need to invent different names");20        System.out.println("✓ Common convention in Java");21    }22}2324class Person {25    private String name;  //?fields26    private int age;27    28    // Parameters have same name as fields  //?constructor29    Person(String name, int age) {30        this.name = name;  //?thisname31        this.age = age;32    }33    34    // Getter - no disambiguation needed  //?getter35    public String getName() {36        return name;  // Just 'name' is fine here37    }38    39    public int getAge() {40        return age;41    }42    43    // Setter - needs 'this' to disambiguate  //?setter44    public void setName(String nameBob) {45        this.name→ Bob = nameBob;  // this.name = field, name = parameter46    }
  8. this.age ← 25

    11        person.setName("Bob");  //?update12        person.setAge(25);13        System.out.println("\nAfter update:");14        System.out.println("Name: " + person.getName());15        System.out.println("Age: " + person.getAge());16        17        System.out.println("\n=== Why Same Names? ===");18        System.out.println("✓ Clear what the parameter represents");19        System.out.println("✓ No need to invent different names");20        System.out.println("✓ Common convention in Java");21    }22}2324class Person {25    private String name;  //?fields26    private int age;27    28    // Parameters have same name as fields  //?constructor29    Person(String name, int age) {30        this.name = name;  //?thisname31        this.age = age;32    }33    34    // Getter - no disambiguation needed  //?getter35    public String getName() {36        return name;  // Just 'name' is fine here37    }38    39    public int getAge() {40        return age;41    }42    43    // Setter - needs 'this' to disambiguate  //?setter44    public void setName(String name) {45        this.name = name;  // this.name = field, name = parameter46    }47    48    public void setAge(int age25) {49        this.age→ 25 = age25;50    }
    output
    After update:
  9. public String getName()

    pass 2 of 2
    34// Getter - no disambiguation needed  //?getter35public String getName() {36    return nameBob;  // Just 'name' is fine here37}
  10. System.out.println("Name: " + person.getName());

    13System.out.println("\nAfter update:");14System.out.println("Name: " + person.getName());15System.out.println("Age: " + person.getAge());
    outputName: Bob
  11. public int getAge()

    pass 2 of 2
    39public int getAge() {40    return age25;41}
  12. System.out.println("Age: " + person.getAge());

    14    System.out.println("Name: " + person.getName());15    System.out.println("Age: " + person.getAge());16    17    System.out.println("\n=== Why Same Names? ===");18    System.out.println("✓ Clear what the parameter represents");19    System.out.println("✓ No need to invent different names");20    System.out.println("✓ Common convention in Java");21}
    outputAge: 25
    
    === Why Same Names? ===
    ✓ Clear what the parameter represents
    ✓ No need to invent different names
    ✓ Common convention in Java

this.name is the field. name alone is the parameter.

this Reference to the current object. Used to access fields and methods.

Method chaining

Return this to enable fluent interfaces.

addAmount
MethodChaining.java
Replay: real traced execution (multi-file project)
public class MethodChaining {
    public static void main(String[] args) {
        System.out.println("=== Method Chaining ===\n");
        int addAmount = 5;

        // Traditional way: separate statements
        Counter counter1 = new Counter();
        counter1.increment();
        counter1.increment();
        counter1.add(addAmount);
        System.out.println("Traditional: " + counter1.getValue());

        // Chained way: single statement
        Counter counter2 = new Counter();
        counter2.increment().increment().add(addAmount);
        System.out.println("Chained: " + counter2.getValue());

        System.out.println("\n=== String Builder Pattern ===");

        // Build message fluently
        MessageBuilder builder = new MessageBuilder();
        String message = builder
            .append("Hello")
            .append(", ")
            .append("World")
            .append("!")
            .build();
        System.out.println("Message: " + message);

        System.out.println("\n=== Benefits ===");
        System.out.println("✓ More concise code");
        System.out.println("✓ Reads like natural language");
        System.out.println("✓ No need for temporary variables");
    }
}

class Counter {
    private int value = 0;

    // Returns 'this' to enable chaining
    public Counter increment() {
        value++;
        return this;  // Return the same object!
    }

    public Counter add(int amount) {
        value += amount;
        return this;  // Return the same object!
    }

    public Counter reset() {
        value = 0;
        return this;
    }

    public int getValue() {
        return value;
    }
}

class MessageBuilder {
    private StringBuilder sb = new StringBuilder();

    public MessageBuilder append(String text) {
        sb.append(text);
        return this;  // Enables: append("a").append("b")
    }

    public MessageBuilder appendLine(String text) {
        sb.append(text).append("\n");
        return this;
    }

    public String build() {
        return sb.toString();
    }
}
public class MethodChaining {
    public static void main(String[] args) {
        System.out.println("=== Method Chaining ===\n");
        int addAmount = 2;

        // Traditional way: separate statements
        Counter counter1 = new Counter();
        counter1.increment();
        counter1.increment();
        counter1.add(addAmount);
        System.out.println("Traditional: " + counter1.getValue());

        // Chained way: single statement
        Counter counter2 = new Counter();
        counter2.increment().increment().add(addAmount);
        System.out.println("Chained: " + counter2.getValue());

        System.out.println("\n=== String Builder Pattern ===");

        // Build message fluently
        MessageBuilder builder = new MessageBuilder();
        String message = builder
            .append("Hello")
            .append(", ")
            .append("World")
            .append("!")
            .build();
        System.out.println("Message: " + message);

        System.out.println("\n=== Benefits ===");
        System.out.println("✓ More concise code");
        System.out.println("✓ Reads like natural language");
        System.out.println("✓ No need for temporary variables");
    }
}

class Counter {
    private int value = 0;

    // Returns 'this' to enable chaining
    public Counter increment() {
        value++;
        return this;  // Return the same object!
    }

    public Counter add(int amount) {
        value += amount;
        return this;  // Return the same object!
    }

    public Counter reset() {
        value = 0;
        return this;
    }

    public int getValue() {
        return value;
    }
}

class MessageBuilder {
    private StringBuilder sb = new StringBuilder();

    public MessageBuilder append(String text) {
        sb.append(text);
        return this;  // Enables: append("a").append("b")
    }

    public MessageBuilder appendLine(String text) {
        sb.append(text).append("\n");
        return this;
    }

    public String build() {
        return sb.toString();
    }
}
public class MethodChaining {
    public static void main(String[] args) {
        System.out.println("=== Method Chaining ===\n");
        int addAmount = 10;

        // Traditional way: separate statements
        Counter counter1 = new Counter();
        counter1.increment();
        counter1.increment();
        counter1.add(addAmount);
        System.out.println("Traditional: " + counter1.getValue());

        // Chained way: single statement
        Counter counter2 = new Counter();
        counter2.increment().increment().add(addAmount);
        System.out.println("Chained: " + counter2.getValue());

        System.out.println("\n=== String Builder Pattern ===");

        // Build message fluently
        MessageBuilder builder = new MessageBuilder();
        String message = builder
            .append("Hello")
            .append(", ")
            .append("World")
            .append("!")
            .build();
        System.out.println("Message: " + message);

        System.out.println("\n=== Benefits ===");
        System.out.println("✓ More concise code");
        System.out.println("✓ Reads like natural language");
        System.out.println("✓ No need for temporary variables");
    }
}

class Counter {
    private int value = 0;

    // Returns 'this' to enable chaining
    public Counter increment() {
        value++;
        return this;  // Return the same object!
    }

    public Counter add(int amount) {
        value += amount;
        return this;  // Return the same object!
    }

    public Counter reset() {
        value = 0;
        return this;
    }

    public int getValue() {
        return value;
    }
}

class MessageBuilder {
    private StringBuilder sb = new StringBuilder();

    public MessageBuilder append(String text) {
        sb.append(text);
        return this;  // Enables: append("a").append("b")
    }

    public MessageBuilder appendLine(String text) {
        sb.append(text).append("\n");
        return this;
    }

    public String build() {
        return sb.toString();
    }
}
  1. addAmount ← 5, counter1 ← ⟨Counter A⟩

    1public class MethodChaining {2    public static void main(String[] args) {3        System.out.println("=== Method Chaining ===\n");4        int addAmount→ 5 = 5;  //@addAmount=2, 105        6        // Traditional way: separate statements  //?traditional7        Counter counter1→ ⟨Counter A⟩ = new Counter();8        counter1.increment();9        counter1.increment();
    output=== Method Chaining ===
  2. value ← 1

    pass 1 of 4
    40// Returns 'this' to enable chaining  //?returnthis41public Counter increment() {42    value→ 1++;43    return this;  // Return the same object!44}
    All 4 passes — pass 1 is the card above
    passamountvalue
    10 1
    21 2
    30 1
    451 2
  3. counter1.increment();

    7Counter counter1 = new Counter();8counter1.increment();9counter1.increment();10counter1.add(addAmount);
  4. counter1.add(addAmount);

    8counter1.increment();9counter1.increment();10counter1.add(addAmount5);11System.out.println("Traditional: " + counter1.getValue());
  5. value ← 7

    pass 1 of 2
    46public Counter add(int amount5) {47    value→ 7 += amount5;48    return this;  // Return the same object!49}
  6. counter1.add(addAmount);

    9counter1.increment();10counter1.add(addAmount5);11System.out.println("Traditional: " + counter1.getValue());
  7. public int getValue()

    pass 1 of 2
    56public int getValue() {57    return value7;58}
  8. counter2 ← ⟨Counter B⟩

    10counter1.add(addAmount);11System.out.println("Traditional: " + counter1.getValue());1213// Chained way: single statement  //?chained14Counter counter2→ ⟨Counter B⟩ = new Counter();15counter2.increment().increment().add(addAmount5);16System.out.println("Chained: " + counter2.getValue());
    outputTraditional: 7
  9. value ← 7

    pass 2 of 2
    46public Counter add(int amount5) {47    value→ 7 += amount5;48    return this;  // Return the same object!49}
  10. counter2.increment().increment().add(addAmount);

    14Counter counter2 = new Counter();15counter2.increment().increment().add(addAmount5);16System.out.println("Chained: " + counter2.getValue());
  11. public int getValue()

    pass 2 of 2
    56public int getValue() {57    return value7;58}
  12. builder ← ⟨MessageBuilder C⟩

    15counter2.increment().increment().add(addAmount);16System.out.println("Chained: " + counter2.getValue());1718System.out.println("\n=== String Builder Pattern ===");1920// Build message fluently  //?stringbuilder21MessageBuilder builder→ ⟨MessageBuilder C⟩ = new MessageBuilder();22String message = builder23    .append("Hello")24    .append(", ")25    .append("World")26    .append("!")27    .build();28System.out.println("Message: " + message);
    outputChained: 7
    
    === String Builder Pattern ===
  13. public MessageBuilder append(String text)

    pass 1 of 4
    64public MessageBuilder append(String textHello) {  //?append65    sb.append(textHello);66    return this;  // Enables: append("a").append("b")67}
    All 4 passes — pass 1 is the card above
    passtext
    1Hello
    2,
    3World
    4!
  14. message ← Hello, World!

    21    MessageBuilder builder = new MessageBuilder();22    String message→ Hello, World! = builder23        .append("Hello")24        .append(", ")25        .append("World")26        .append("!")27        .build();28    System.out.println("Message: " + messageHello, World!);29    30    System.out.println("\n=== Benefits ===");31    System.out.println("✓ More concise code");32    System.out.println("✓ Reads like natural language");33    System.out.println("✓ No need for temporary variables");34}
    outputMessage: Hello, World!
    
    === Benefits ===
    ✓ More concise code
    ✓ Reads like natural language
    ✓ No need for temporary variables
  1. addAmount ← 2, counter1 ← ⟨Counter A⟩

    1public class MethodChaining {2    public static void main(String[] args) {3        System.out.println("=== Method Chaining ===\n");4        int addAmount→ 2 = 2;5        6        // Traditional way: separate statements7        Counter counter1→ ⟨Counter A⟩ = new Counter();8        counter1.increment();9        counter1.increment();
    output=== Method Chaining ===
  2. value ← 1

    pass 1 of 4
    40// Returns 'this' to enable chaining41public Counter increment() {42    value→ 1++;43    return this;  // Return the same object!44}
    All 4 passes — pass 1 is the card above
    passamountvalue
    10 1
    21 2
    30 1
    421 2
  3. counter1.increment();

    7Counter counter1 = new Counter();8counter1.increment();9counter1.increment();10counter1.add(addAmount);
  4. counter1.add(addAmount);

    8counter1.increment();9counter1.increment();10counter1.add(addAmount2);11System.out.println("Traditional: " + counter1.getValue());
  5. value ← 4

    pass 1 of 2
    46public Counter add(int amount2) {47    value→ 4 += amount2;48    return this;  // Return the same object!49}
  6. counter1.add(addAmount);

    9counter1.increment();10counter1.add(addAmount2);11System.out.println("Traditional: " + counter1.getValue());
  7. public int getValue()

    pass 1 of 2
    56public int getValue() {57    return value4;58}
  8. counter2 ← ⟨Counter B⟩

    10counter1.add(addAmount);11System.out.println("Traditional: " + counter1.getValue());1213// Chained way: single statement14Counter counter2→ ⟨Counter B⟩ = new Counter();15counter2.increment().increment().add(addAmount2);16System.out.println("Chained: " + counter2.getValue());
    outputTraditional: 4
  9. value ← 4

    pass 2 of 2
    46public Counter add(int amount2) {47    value→ 4 += amount2;48    return this;  // Return the same object!49}
  10. counter2.increment().increment().add(addAmount);

    14Counter counter2 = new Counter();15counter2.increment().increment().add(addAmount2);16System.out.println("Chained: " + counter2.getValue());
  11. public int getValue()

    pass 2 of 2
    56public int getValue() {57    return value4;58}
  12. builder ← ⟨MessageBuilder C⟩

    15counter2.increment().increment().add(addAmount);16System.out.println("Chained: " + counter2.getValue());1718System.out.println("\n=== String Builder Pattern ===");1920// Build message fluently21MessageBuilder builder→ ⟨MessageBuilder C⟩ = new MessageBuilder();22String message = builder23    .append("Hello")24    .append(", ")25    .append("World")26    .append("!")27    .build();28System.out.println("Message: " + message);
    outputChained: 4
    
    === String Builder Pattern ===
  13. public MessageBuilder append(String text)

    pass 1 of 4
    64public MessageBuilder append(String textHello) {65    sb.append(textHello);66    return this;  // Enables: append("a").append("b")67}
    All 4 passes — pass 1 is the card above
    passtext
    1Hello
    2,
    3World
    4!
  14. message ← Hello, World!

    21    MessageBuilder builder = new MessageBuilder();22    String message→ Hello, World! = builder23        .append("Hello")24        .append(", ")25        .append("World")26        .append("!")27        .build();28    System.out.println("Message: " + messageHello, World!);29    30    System.out.println("\n=== Benefits ===");31    System.out.println("✓ More concise code");32    System.out.println("✓ Reads like natural language");33    System.out.println("✓ No need for temporary variables");34}
    outputMessage: Hello, World!
    
    === Benefits ===
    ✓ More concise code
    ✓ Reads like natural language
    ✓ No need for temporary variables
  1. addAmount ← 10, counter1 ← ⟨Counter A⟩

    1public class MethodChaining {2    public static void main(String[] args) {3        System.out.println("=== Method Chaining ===\n");4        int addAmount→ 10 = 10;5        6        // Traditional way: separate statements7        Counter counter1→ ⟨Counter A⟩ = new Counter();8        counter1.increment();9        counter1.increment();
    output=== Method Chaining ===
  2. value ← 1

    pass 1 of 4
    40// Returns 'this' to enable chaining41public Counter increment() {42    value→ 1++;43    return this;  // Return the same object!44}
    All 4 passes — pass 1 is the card above
    passamountvalue
    10 1
    21 2
    30 1
    4101 2
  3. counter1.increment();

    7Counter counter1 = new Counter();8counter1.increment();9counter1.increment();10counter1.add(addAmount);
  4. counter1.add(addAmount);

    8counter1.increment();9counter1.increment();10counter1.add(addAmount10);11System.out.println("Traditional: " + counter1.getValue());
  5. value ← 12

    pass 1 of 2
    46public Counter add(int amount10) {47    value→ 12 += amount10;48    return this;  // Return the same object!49}
  6. counter1.add(addAmount);

    9counter1.increment();10counter1.add(addAmount10);11System.out.println("Traditional: " + counter1.getValue());
  7. public int getValue()

    pass 1 of 2
    56public int getValue() {57    return value12;58}
  8. counter2 ← ⟨Counter B⟩

    10counter1.add(addAmount);11System.out.println("Traditional: " + counter1.getValue());1213// Chained way: single statement14Counter counter2→ ⟨Counter B⟩ = new Counter();15counter2.increment().increment().add(addAmount10);16System.out.println("Chained: " + counter2.getValue());
    outputTraditional: 12
  9. value ← 12

    pass 2 of 2
    46public Counter add(int amount10) {47    value→ 12 += amount10;48    return this;  // Return the same object!49}
  10. counter2.increment().increment().add(addAmount);

    14Counter counter2 = new Counter();15counter2.increment().increment().add(addAmount10);16System.out.println("Chained: " + counter2.getValue());
  11. public int getValue()

    pass 2 of 2
    56public int getValue() {57    return value12;58}
  12. builder ← ⟨MessageBuilder C⟩

    15counter2.increment().increment().add(addAmount);16System.out.println("Chained: " + counter2.getValue());1718System.out.println("\n=== String Builder Pattern ===");1920// Build message fluently21MessageBuilder builder→ ⟨MessageBuilder C⟩ = new MessageBuilder();22String message = builder23    .append("Hello")24    .append(", ")25    .append("World")26    .append("!")27    .build();28System.out.println("Message: " + message);
    outputChained: 12
    
    === String Builder Pattern ===
  13. public MessageBuilder append(String text)

    pass 1 of 4
    64public MessageBuilder append(String textHello) {65    sb.append(textHello);66    return this;  // Enables: append("a").append("b")67}
    All 4 passes — pass 1 is the card above
    passtext
    1Hello
    2,
    3World
    4!
  14. message ← Hello, World!

    21    MessageBuilder builder = new MessageBuilder();22    String message→ Hello, World! = builder23        .append("Hello")24        .append(", ")25        .append("World")26        .append("!")27        .build();28    System.out.println("Message: " + messageHello, World!);29    30    System.out.println("\n=== Benefits ===");31    System.out.println("✓ More concise code");32    System.out.println("✓ Reads like natural language");33    System.out.println("✓ No need for temporary variables");34}
    outputMessage: Hello, World!
    
    === Benefits ===
    ✓ More concise code
    ✓ Reads like natural language
    ✓ No need for temporary variables

return this allows obj.setX(1).setY(2).setZ(3).

fluent interface Methods return `this` for chaining: `builder.setA(1).setB(2).build()`.

Pass this to other methods

Give the current object to another method or class.

PassThis.java
Replay: real traced execution (multi-file project)
public class PassThis {
    public static void main(String[] args) {
        System.out.println("=== Passing 'this' to Methods ===\n");

        // Create registrar and tasks
        TaskRegistry registry = new TaskRegistry();

        Task task1 = new Task("Learn Java", registry);
        Task task2 = new Task("Practice coding", registry);
        Task task3 = new Task("Build projects", registry);

        System.out.println("=== Registry Status ===");
        registry.showAll();

        System.out.println("\n=== Completing a Task ===");
        task2.complete();

        System.out.println("\n=== Registry After Completion ===");
        registry.showAll();
    }
}

class Task {
    private String name;
    private boolean completed = false;

    Task(String name, TaskRegistry registry) {
        this.name = name;
        registry.register(this);
    }

    void complete() {
        completed = true;
        System.out.println("Completed: " + name);
    }

    String getStatus() {
        return name + (completed ? " [DONE]" : " [pending]");
    }
}

class TaskRegistry {
    private Task[] tasks = new Task[10];
    private int count = 0;

    void register(Task task) {
        if (count < tasks.length) {
            tasks[count++] = task;
            System.out.println("Registered: " + task.getStatus());
        }
    }

    void showAll() {
        System.out.println("All tasks (" + count + "):");
        for (int i = 0; i < count; i++) {
            System.out.println("  " + (i + 1) + ". " + tasks[i].getStatus());
        }
    }
}
  1. registry ← ⟨TaskRegistry A⟩

    1public class PassThis {2    public static void main(String[] args) {3        System.out.println("=== Passing 'this' to Methods ===\n");4        5        // Create registrar and tasks  //?setup6        TaskRegistry registry→ ⟨TaskRegistry A⟩ = new TaskRegistry();7        8        Task task1 = new Task("Learn Java", registry);  //?createtask9        Task task2 = new Task("Practice coding", registry);
    output=== Passing 'this' to Methods ===
  2. this.name ← Learn Java

    pass 1 of 3
    27Task(String nameLearn Java, TaskRegistry registry⟨TaskRegistry A⟩) {  //?taskctr28    this.name→ Learn Java = nameLearn Java;29    registry.register(this);  //?passthis30}
    All 3 passes — pass 1 is the card above
    passnamethis.name
    1Learn JavaLearn Java
    2Practice codingPractice coding
    3Build projectsBuild projects
  3. void register(Task task)

    pass 1 of 3
    46void register(Task task⟨Task B⟩) {  //?register47    if (count < tasks.length) {
    All 3 passes — pass 1 is the card above
    passtask
    1⟨Task B⟩
    2⟨Task C⟩
    3⟨Task D⟩
  4. count ← 1

    pass 1 of 3
    46void register(Task task) {  //?register47    if (count0 < tasks.length10) {48        tasks[count→ 1++] = task⟨Task B⟩;49        System.out.println("Registered: " + task.getStatus());50    }
    All 3 passes — pass 1 is the card above
    passtaskcount
    1⟨Task B⟩0 1
    2⟨Task C⟩1 2
    3⟨Task D⟩2 3
  5. String getStatus()

    pass 1 of 9
    37String getStatus() {38    return nameLearn Java + (completedfalse ? " [DONE]" : " [pending]");39}
    All 9 passes — pass 1 is the card above
    passnamecompleted
    1Learn Javafalse
    2Practice codingfalse
    3Build projectsfalse
    4Learn Javafalse
    5Practice codingfalse
    6Build projectsfalse
    7Learn Javafalse
    8Practice codingtrue
    9Build projectsfalse
  6. task1 ← ⟨Task B⟩

    8        Task task1→ ⟨Task B⟩ = new Task("Learn Java", registry);  //?createtask9        Task task2 = new Task("Practice coding", registry);10        Task task3 = new Task("Build projects", registry);11        12        System.out.println("=== Registry Status ===");13        registry.showAll();14        15        System.out.println("\n=== Completing a Task ===");16        task2.complete();  //?complete17        18        System.out.println("\n=== Registry After Completion ===");19        registry.showAll();20    }21}2223class Task {24    private String name;25    private boolean completed = false;26    27    Task(String name, TaskRegistry registry) {  //?taskctr28        this.name = name;29        registry.register(this);  //?passthis30    }31    32    void complete() {33        completed = true;34        System.out.println("Completed: " + name);35    }36    37    String getStatus() {38        return name + (completed ? " [DONE]" : " [pending]");39    }40}4142class TaskRegistry {43    private Task[] tasks = new Task[10];  //?registry44    private int count = 0;45    46    void register(Task task) {  //?register47        if (count < tasks.length) {48            tasks[count++] = task;49            System.out.println("Registered: " + task.getStatus());50        }
    outputRegistered: Learn Java [pending]
  7. task2 ← ⟨Task C⟩

    8        Task task1 = new Task("Learn Java", registry);  //?createtask9        Task task2→ ⟨Task C⟩ = new Task("Practice coding", registry);10        Task task3 = new Task("Build projects", registry);11        12        System.out.println("=== Registry Status ===");13        registry.showAll();14        15        System.out.println("\n=== Completing a Task ===");16        task2.complete();  //?complete17        18        System.out.println("\n=== Registry After Completion ===");19        registry.showAll();20    }21}2223class Task {24    private String name;25    private boolean completed = false;26    27    Task(String name, TaskRegistry registry) {  //?taskctr28        this.name = name;29        registry.register(this);  //?passthis30    }31    32    void complete() {33        completed = true;34        System.out.println("Completed: " + name);35    }36    37    String getStatus() {38        return name + (completed ? " [DONE]" : " [pending]");39    }40}4142class TaskRegistry {43    private Task[] tasks = new Task[10];  //?registry44    private int count = 0;45    46    void register(Task task) {  //?register47        if (count < tasks.length) {48            tasks[count++] = task;49            System.out.println("Registered: " + task.getStatus());50        }
    outputRegistered: Practice coding [pending]
  8. task3 ← ⟨Task D⟩

    9        Task task2 = new Task("Practice coding", registry);10        Task task3→ ⟨Task D⟩ = new Task("Build projects", registry);11        12        System.out.println("=== Registry Status ===");13        registry.showAll();14        15        System.out.println("\n=== Completing a Task ===");16        task2.complete();  //?complete17        18        System.out.println("\n=== Registry After Completion ===");19        registry.showAll();20    }21}2223class Task {24    private String name;25    private boolean completed = false;26    27    Task(String name, TaskRegistry registry) {  //?taskctr28        this.name = name;29        registry.register(this);  //?passthis30    }31    32    void complete() {33        completed = true;34        System.out.println("Completed: " + name);35    }36    37    String getStatus() {38        return name + (completed ? " [DONE]" : " [pending]");39    }40}4142class TaskRegistry {43    private Task[] tasks = new Task[10];  //?registry44    private int count = 0;45    46    void register(Task task) {  //?register47        if (count < tasks.length) {48            tasks[count++] = task;49            System.out.println("Registered: " + task.getStatus());50        }
    outputRegistered: Build projects [pending]
    === Registry Status ===
  9. void showAll()

    pass 1 of 2
    53void showAll() {54    System.out.println("All tasks (" + count3 + "):");55    for (int i = 0; i < count; i++) {
    outputAll tasks (3):
  10. for (int i = 0; i < count; i++)

    pass 1 of 6
    54System.out.println("All tasks (" + count + "):");55for (int i0 = 0; i < count3; i++) {56    System.out.println("  " + (i0 + 1) + ". " + tasks[i]⟨Task B⟩.getStatus());57}
    All 6 passes — pass 1 is the card above
    passitasks[i]
    10⟨Task B⟩
    21⟨Task C⟩
    32⟨Task D⟩
    40⟨Task B⟩
    51⟨Task C⟩
    62⟨Task D⟩
  11. System.out.println(" " + (i + 1) + ". " + tasks[i].getStatus());

    55for (int i = 0; i < count; i++) {56    System.out.println("  " + (i0 + 1) + ". " + tasks[i]⟨Task B⟩.getStatus());57}
    output  1. Learn Java [pending]
  12. System.out.println(" " + (i + 1) + ". " + tasks[i].getStatus());

    55for (int i = 0; i < count; i++) {56    System.out.println("  " + (i1 + 1) + ". " + tasks[i]⟨Task C⟩.getStatus());57}
    output  2. Practice coding [pending]
  13. System.out.println(" " + (i + 1) + ". " + tasks[i].getStatus());

    12        System.out.println("=== Registry Status ===");13        registry.showAll();14        15        System.out.println("\n=== Completing a Task ===");16        task2.complete();  //?complete17        18        System.out.println("\n=== Registry After Completion ===");19        registry.showAll();20    }21}2223class Task {24    private String name;25    private boolean completed = false;26    27    Task(String name, TaskRegistry registry) {  //?taskctr28        this.name = name;29        registry.register(this);  //?passthis30    }31    32    void complete() {33        completed = true;34        System.out.println("Completed: " + name);35    }36    37    String getStatus() {38        return name + (completed ? " [DONE]" : " [pending]");39    }40}4142class TaskRegistry {43    private Task[] tasks = new Task[10];  //?registry44    private int count = 0;45    46    void register(Task task) {  //?register47        if (count < tasks.length) {48            tasks[count++] = task;49            System.out.println("Registered: " + task.getStatus());50        }51    }52    53    void showAll() {54        System.out.println("All tasks (" + count + "):");55        for (int i = 0; i < count; i++) {56            System.out.println("  " + (i2 + 1) + ". " + tasks[i]⟨Task D⟩.getStatus());57        }
    output  3. Build projects [pending]
    
    === Completing a Task ===
  14. completed ← true

    15        System.out.println("\n=== Completing a Task ===");16        task2.complete();  //?complete17        18        System.out.println("\n=== Registry After Completion ===");19        registry.showAll();20    }21}2223class Task {24    private String name;25    private boolean completed = false;26    27    Task(String name, TaskRegistry registry) {  //?taskctr28        this.name = name;29        registry.register(this);  //?passthis30    }31    32    void complete() {33        completed→ true = true;34        System.out.println("Completed: " + namePractice coding);35    }
    outputCompleted: Practice coding
    
    === Registry After Completion ===
  15. void showAll()

    pass 2 of 2
    53void showAll() {54    System.out.println("All tasks (" + count3 + "):");55    for (int i = 0; i < count; i++) {
    outputAll tasks (3):
  16. System.out.println(" " + (i + 1) + ". " + tasks[i].getStatus());

    55for (int i = 0; i < count; i++) {56    System.out.println("  " + (i0 + 1) + ". " + tasks[i]⟨Task B⟩.getStatus());57}
    output  1. Learn Java [pending]
  17. System.out.println(" " + (i + 1) + ". " + tasks[i].getStatus());

    55for (int i = 0; i < count; i++) {56    System.out.println("  " + (i1 + 1) + ". " + tasks[i]⟨Task C⟩.getStatus());57}
    output  2. Practice coding [DONE]
  18. System.out.println(" " + (i + 1) + ". " + tasks[i].getStatus());

    18        System.out.println("\n=== Registry After Completion ===");19        registry.showAll();20    }21}2223class Task {24    private String name;25    private boolean completed = false;26    27    Task(String name, TaskRegistry registry) {  //?taskctr28        this.name = name;29        registry.register(this);  //?passthis30    }31    32    void complete() {33        completed = true;34        System.out.println("Completed: " + name);35    }36    37    String getStatus() {38        return name + (completed ? " [DONE]" : " [pending]");39    }40}4142class TaskRegistry {43    private Task[] tasks = new Task[10];  //?registry44    private int count = 0;45    46    void register(Task task) {  //?register47        if (count < tasks.length) {48            tasks[count++] = task;49            System.out.println("Registered: " + task.getStatus());50        }51    }52    53    void showAll() {54        System.out.println("All tasks (" + count + "):");55        for (int i = 0; i < count; i++) {56            System.out.println("  " + (i2 + 1) + ". " + tasks[i]⟨Task D⟩.getStatus());57        }
    output  3. Build projects [pending]

someMethod(this) passes the current object as an argument.

Call another constructor

Use this() to invoke a different constructor.

ThisConstructor.java
Replay: real traced execution (multi-file project)
public class ThisConstructor {
    public static void main(String[] args) {
        System.out.println("=== this() Constructor Calls ===\n");

        // Different ways to create Rectangle
        Rectangle r1 = new Rectangle();
        System.out.println("1. " + r1);

        Rectangle r2 = new Rectangle(5);  // Square
        System.out.println("2. " + r2);

        Rectangle r3 = new Rectangle(4, 6);
        System.out.println("3. " + r3);

        System.out.println("\n=== Notice Constructor Chain ===");
        System.out.println("Each simpler constructor calls a more complete one.");
        System.out.println("All eventually reach the main constructor.");
    }
}

class Rectangle {
    private double width;
    private double height;

    // Main constructor - all logic here
    Rectangle(double width, double height) {
        System.out.println("  [Main constructor: " + width + "x" + height + "]");
        this.width = Math.max(0, width);   // Validation
        this.height = Math.max(0, height);
    }

    // Square constructor - delegates to main
    Rectangle(double side) {
        this(side, side);  // Must be FIRST statement!
        System.out.println("  [Square constructor]");
    }

    // Default constructor - delegates to square
    Rectangle() {
        this(1);  // Unit square
        System.out.println("  [Default constructor]");
    }

    @Override
    public String toString() {
        return "Rectangle " + width + "x" + height;
    }
}
  1. public static void main(String[] args)

    1public class ThisConstructor {2    public static void main(String[] args) {3        System.out.println("=== this() Constructor Calls ===\n");4        5        // Different ways to create Rectangle  //?create6        Rectangle r1 = new Rectangle();7        System.out.println("1. " + r1);
    output=== this() Constructor Calls ===
  2. this.width ← 1.0, this.height ← 1.0

    pass 1 of 3
    25// Main constructor - all logic here  //?main26Rectangle(double width1.0, double height1.0) {27    System.out.println("  [Main constructor: " + width1.0 + "x" + height1.0 + "]");28    this.width→ 1.0 = Math.max(0, width1.0);   // Validation29    this.height→ 1.0 = Math.max(0, height1.0);30}
    output  [Main constructor: 1.0x1.0]
    All 3 passes — pass 1 is the card above
    passwidthheightsidethis.widththis.heightr1r2r3
    11.01.01.01.01.0Rectangle 1.0x1.0
    25.05.05.05.05.0Rectangle 5.0x5.0
    34.06.04.06.0Rectangle 4.0x6.0
  3. Rectangle(double side)

    pass 1 of 2
    32// Square constructor - delegates to main  //?square33Rectangle(double side1.0) {34    this(side, side);  // Must be FIRST statement!35    System.out.println("  [Square constructor]");36}
    output  [Square constructor]
  4. r1 ← Rectangle 1.0x1.0

    5        // Different ways to create Rectangle  //?create6        Rectangle r1→ Rectangle 1.0x1.0 = new Rectangle();7        System.out.println("1. " + r1Rectangle 1.0x1.0);8        9        Rectangle r2 = new Rectangle(5);  // Square10        System.out.println("2. " + r2);11        12        Rectangle r3 = new Rectangle(4, 6);13        System.out.println("3. " + r3);14        15        System.out.println("\n=== Notice Constructor Chain ===");16        System.out.println("Each simpler constructor calls a more complete one.");17        System.out.println("All eventually reach the main constructor.");18    }19}2021class Rectangle {22    private double width;23    private double height;24    25    // Main constructor - all logic here  //?main26    Rectangle(double width, double height) {27        System.out.println("  [Main constructor: " + width + "x" + height + "]");28        this.width = Math.max(0, width);   // Validation29        this.height = Math.max(0, height);30    }31    32    // Square constructor - delegates to main  //?square33    Rectangle(double side) {34        this(side, side);  // Must be FIRST statement!35        System.out.println("  [Square constructor]");36    }37    38    // Default constructor - delegates to square  //?default39    Rectangle() {40        this(1);  // Unit square41        System.out.println("  [Default constructor]");42    }
    output  [Default constructor]
    1. Rectangle 1.0x1.0
  5. r2 ← Rectangle 5.0x5.0

    pass 2 of 2
    9        Rectangle r2→ Rectangle 5.0x5.0 = new Rectangle(5);  // Square10        System.out.println("2. " + r2Rectangle 5.0x5.0);11        12        Rectangle r3 = new Rectangle(4, 6);13        System.out.println("3. " + r3);14        15        System.out.println("\n=== Notice Constructor Chain ===");16        System.out.println("Each simpler constructor calls a more complete one.");17        System.out.println("All eventually reach the main constructor.");18    }19}2021class Rectangle {22    private double width;23    private double height;24    25    // Main constructor - all logic here  //?main26    Rectangle(double width, double height) {27        System.out.println("  [Main constructor: " + width + "x" + height + "]");28        this.width = Math.max(0, width);   // Validation29        this.height = Math.max(0, height);30    }31    32    // Square constructor - delegates to main  //?square33    Rectangle(double side5.0) {34        this(side, side);  // Must be FIRST statement!35        System.out.println("  [Square constructor]");36    }
    output  [Square constructor]
    2. Rectangle 5.0x5.0

this(args) calls another constructor. Must be first line.

Builder pattern

Combine method chaining with a separate builder class.

BuilderPattern.java
Replay: real traced execution (multi-file project)
public class BuilderPattern {
    public static void main(String[] args) {
        System.out.println("=== Builder Pattern ===\n");

        // Build an email step by step
        Email email = new EmailBuilder()
            .from("alice@example.com")
            .to("bob@example.com")
            .subject("Meeting Tomorrow")
            .body("Hi Bob,\nLet's meet at 10am.\n- Alice")
            .priority(EmailBuilder.Priority.HIGH)
            .build();

        System.out.println(email);

        System.out.println("\n=== Another Email ===");

        // Simpler email with defaults
        Email simple = new EmailBuilder()
            .to("team@example.com")
            .subject("Quick update")
            .build();

        System.out.println(simple);

        System.out.println("\n=== Benefits ===");
        System.out.println("✓ Optional parameters made easy");
        System.out.println("✓ Readable, self-documenting");
        System.out.println("✓ Immutable result object");
    }
}

class EmailBuilder {
    // Builder fields with defaults
    private String from = "noreply@example.com";
    private String to = "";
    private String subject = "(no subject)";
    private String body = "";
    private Priority priority = Priority.NORMAL;

    enum Priority { LOW, NORMAL, HIGH, URGENT }

    // Each setter returns 'this'
    public EmailBuilder from(String from) {
        this.from = from;
        return this;  // Enable chaining
    }

    public EmailBuilder to(String to) {
        this.to = to;
        return this;
    }

    public EmailBuilder subject(String subject) {
        this.subject = subject;
        return this;
    }

    public EmailBuilder body(String body) {
        this.body = body;
        return this;
    }

    public EmailBuilder priority(Priority priority) {
        this.priority = priority;
        return this;
    }

    // Final build method creates the object
    public Email build() {
        if (to.isEmpty()) {
            throw new IllegalStateException("'to' is required");
        }
        return new Email(from, to, subject, body, priority.name());
    }
}

class Email {
    private final String from, to, subject, body, priority;

    Email(String from, String to, String subject, String body, String priority) {
        this.from = from;
        this.to = to;
        this.subject = subject;
        this.body = body;
        this.priority = priority;
    }

    @Override
    public String toString() {
        return String.format(
            "=== Email [%s] ===\nFrom: %s\nTo: %s\nSubject: %s\n---\n%s",
            priority, from, to, subject, body.isEmpty() ? "(no body)" : body
        );
    }
}
  1. public static void main(String[] args)

    1public class BuilderPattern {2    public static void main(String[] args) {3        System.out.println("=== Builder Pattern ===\n");4        5        // Build an email step by step  //?build6        Email email = new EmailBuilder()7            .from("alice@example.com")8            .to("bob@example.com")9            .subject("Meeting Tomorrow")10            .body("Hi Bob,\nLet's meet at 10am.\n- Alice")11            .priority(EmailBuilder.Priority.HIGH)12            .build();
    output=== Builder Pattern ===
  2. this.from ← alice@example.com

    43// Each setter returns 'this'  //?setters44public EmailBuilder from(String fromalice@example.com) {45    this.from→ alice@example.com = fromalice@example.com;46    return this;  // Enable chaining47}
  3. this.to ← bob@example.com

    pass 1 of 2
    49public EmailBuilder to(String to) {50    this.to→ bob@example.com = tobob@example.com;51    return this;52}
  4. this.subject ← Meeting Tomorrow

    pass 1 of 2
    54public EmailBuilder subject(String subjectMeeting Tomorrow) {55    this.subject→ Meeting Tomorrow = subjectMeeting Tomorrow;56    return this;57}
  5. this.body ← Hi Bob, Let's meet at 10am. - Alice

    59public EmailBuilder body(String bodyHi Bob,
    Let's meet at 10am.
    - Alice) {60    this.body→ Hi Bob,
    Let's meet at 10am.
    - Alice = bodyHi Bob,
    Let's meet at 10am.
    - Alice;61    return this;62}
  6. this.priority ← HIGH

    64public EmailBuilder priority(Priority priorityHIGH) {65    this.priority→ HIGH = priorityHIGH;66    return this;67}
  7. this.from ← alice@example.com, this.to ← bob@example.com, this.subject ← Meeting Tomorrow

    pass 1 of 2
    5        // Build an email step by step  //?build6        Email email→ === Email [HIGH] ===
    From: alice@example.com
    To: bob@example.com
    Subject: Meeting Tomorrow
    ---
    Hi Bob,
    Let's meet at 10am.
    - Alice = new EmailBuilder()7            .from("alice@example.com")8            .to("bob@example.com")9            .subject("Meeting Tomorrow")10            .body("Hi Bob,\nLet's meet at 10am.\n- Alice")11            .priority(EmailBuilder.Priority.HIGH)12            .build();13        14        System.out.println(email=== Email [HIGH] ===
    From: alice@example.com
    To: bob@example.com
    Subject: Meeting Tomorrow
    ---
    Hi Bob,
    Let's meet at 10am.
    - Alice);15        16        System.out.println("\n=== Another Email ===");17        18        // Simpler email with defaults  //?simple19        Email simple = new EmailBuilder()20            .to("team@example.com")21            .subject("Quick update")22            .build();23        24        System.out.println(simple);25        26        System.out.println("\n=== Benefits ===");27        System.out.println("✓ Optional parameters made easy");28        System.out.println("✓ Readable, self-documenting");29        System.out.println("✓ Immutable result object");30    }31}3233class EmailBuilder {34    // Builder fields with defaults  //?fields35    private String from = "noreply@example.com";36    private String to = "";37    private String subject = "(no subject)";38    private String body = "";39    private Priority priority = Priority.NORMAL;40    41    enum Priority { LOW, NORMAL, HIGH, URGENT }42    43    // Each setter returns 'this'  //?setters44    public EmailBuilder from(String from) {45        this.from = from;46        return this;  // Enable chaining47    }48    49    public EmailBuilder to(String to) {50        this.to = to;51        return this;52    }53    54    public EmailBuilder subject(String subject) {55        this.subject = subject;56        return this;57    }58    59    public EmailBuilder body(String body) {60        this.body = body;61        return this;62    }63    64    public EmailBuilder priority(Priority priority) {65        this.priority = priority;66        return this;67    }68    69    // Final build method creates the object  //?buildmethod70    public Email build() {71        if (to.isEmpty()) {72            throw new IllegalStateException("'to' is required");73        }74        return new Email(from, to, subject, body, priority.name());75    }76}7778class Email {79    private final String from, to, subject, body, priority;  //?emailfields80    81    Email(String fromalice@example.com, String to, String subjectMeeting Tomorrow, String bodyHi Bob,
    Let's meet at 10am.
    - Alice, String priorityHIGH) {82        this.from→ alice@example.com = fromalice@example.com;83        this.to→ bob@example.com = tobob@example.com;84        this.subject→ Meeting Tomorrow = subjectMeeting Tomorrow;85        this.body→ Hi Bob,
    Let's meet at 10am.
    - Alice = bodyHi Bob,
    Let's meet at 10am.
    - Alice;86        this.priority→ HIGH = priorityHIGH;87    }
    output=== Email [HIGH] ===
    From: alice@example.com
    To: bob@example.com
    Subject: Meeting Tomorrow
    ---
    Hi Bob,
    Let's meet at 10am.
    - Alice
    
    === Another Email ===
  8. this.to ← team@example.com

    pass 2 of 2
    49public EmailBuilder to(String to) {50    this.to→ team@example.com = toteam@example.com;51    return this;52}
  9. this.subject ← Quick update

    pass 2 of 2
    54public EmailBuilder subject(String subjectQuick update) {55    this.subject→ Quick update = subjectQuick update;56    return this;57}
  10. this.from ← noreply@example.com, this.to ← team@example.com, this.subject ← Quick update

    pass 2 of 2
    18        // Simpler email with defaults  //?simple19        Email simple→ === Email [NORMAL] ===
    From: noreply@example.com
    To: team@example.com
    Subject: Quick update
    ---
    (no body) = new EmailBuilder()20            .to("team@example.com")21            .subject("Quick update")22            .build();23        24        System.out.println(simple=== Email [NORMAL] ===
    From: noreply@example.com
    To: team@example.com
    Subject: Quick update
    ---
    (no body));25        26        System.out.println("\n=== Benefits ===");27        System.out.println("✓ Optional parameters made easy");28        System.out.println("✓ Readable, self-documenting");29        System.out.println("✓ Immutable result object");30    }31}3233class EmailBuilder {34    // Builder fields with defaults  //?fields35    private String from = "noreply@example.com";36    private String to = "";37    private String subject = "(no subject)";38    private String body = "";39    private Priority priority = Priority.NORMAL;40    41    enum Priority { LOW, NORMAL, HIGH, URGENT }42    43    // Each setter returns 'this'  //?setters44    public EmailBuilder from(String from) {45        this.from = from;46        return this;  // Enable chaining47    }48    49    public EmailBuilder to(String to) {50        this.to = to;51        return this;52    }53    54    public EmailBuilder subject(String subject) {55        this.subject = subject;56        return this;57    }58    59    public EmailBuilder body(String body) {60        this.body = body;61        return this;62    }63    64    public EmailBuilder priority(Priority priority) {65        this.priority = priority;66        return this;67    }68    69    // Final build method creates the object  //?buildmethod70    public Email build() {71        if (to.isEmpty()) {72            throw new IllegalStateException("'to' is required");73        }74        return new Email(from, to, subject, body, priority.name());75    }76}7778class Email {79    private final String from, to, subject, body, priority;  //?emailfields80    81    Email(String fromnoreply@example.com, String to, String subjectQuick update, String body(empty), String priorityNORMAL) {82        this.from→ noreply@example.com = fromnoreply@example.com;83        this.to→ team@example.com = toteam@example.com;84        this.subject→ Quick update = subjectQuick update;85        this.body→ (empty) = body(empty);86        this.priority→ NORMAL = priorityNORMAL;87    }
    output=== Email [NORMAL] ===
    From: noreply@example.com
    To: team@example.com
    Subject: Quick update
    ---
    (no body)
    
    === Benefits ===
    ✓ Optional parameters made easy
    ✓ Readable, self-documenting
    ✓ Immutable result object

Builder accumulates settings, then creates the final object.

Exercise: CompleteExample.java

Comprehensive example combining all uses of this