CodingNeed.

2 · Model and validate · 25 MIN

Records and value-oriented modeling

Records make a small data carrier’s components explicit.

A record supplies accessors, equality, hashCode and a readable representation based on its components. A compact constructor can reject invalid values before an instance exists. This prevents every caller from having to remember the same basic check. Records are only shallowly immutable: a final reference to a mutable collection still permits that collection to change. Use defensive copies when a record must own a collection. Here the components are String and int, so there is no collection alias to manage.

Validate construction and copy mutable inputs at the ownership boundary.

Read the example

public class Main {
  record Expense(String category, int amount) {
    Expense {
      if (category == null || category.isBlank() || amount < 0)
        throw new IllegalArgumentException("Invalid expense");
    }
  }
  public static void main(String[] args) {
    var first = new Expense("food",5);
    System.out.println(first.category());
    System.out.println(first.equals(new Expense("food",5)));
  }
}
Check the expected output
food
true

Your challenge

Create a Basket record containing a list of Expense values and preserve an immutable snapshot using List.copyOf.

Solution cost: O(1) construction for the scalar example; copying n items costs O(n). time · Account for collection storage separately from the returned result. space

Common trap

A record containing a mutable list is not deeply immutable automatically.

Study the project implementation
public class Main {
  record Expense(String category, int amount) {
    Expense {
      if (category == null || category.isBlank() || amount < 0)
        throw new IllegalArgumentException("Invalid expense");
    }
  }
  public static void main(String[] args) {
    var first = new Expense("food",5);
    System.out.println(first.category());
    System.out.println(first.equals(new Expense("food",5)));
  }
}

Further reading: Official documentation

Next lesson: Parsing and exception boundaries

Essential cookies keep your account signed in. Optional analytics is not configured on this site. Your choice does not affect access to lessons.

Read the Privacy Policy. You can change this choice in the footer.