• 🎬 Canonical Constructor

    – The Long Way

    We begin with a record named FrenchActor. We want to ensure that no actor has a negative number of awards. Here's how we could write this using a canonical constructor (with full parameter declaration):

    record FrenchActor(String name, int cesarAwards) {
        public FrenchActor(String name, int cesarAwards) {
            if (cesarAwards < 0) {
                throw new IllegalArgumentException(
                    String.format("Invalid number of César Awards for %s: %d", 
                    name, cesarAwards));
            }
            this.name = name;
            this.cesarAwards = cesarAwards;
        }
    }

    Here, we are manually repeating the record components in the constructor signature and assigning them to fields. It works, but it’s verbose and repetitive.

    🎬 Compact Constructor – The Elegant Way

    To simplify things, records let us declare a compact constructor. The parameter list is implied, and the assignments to fields are done automatically:

    record FrenchActor(String name, int cesarAwards) {
        public FrenchActor {
            if (cesarAwards < 0) {
                throw new IllegalArgumentException(
                    String.format("Invalid number of César Awards for %s: %d", 
                    name, cesarAwards));
            }
        }
    }

    This version is cleaner, avoids repetition, and still performs the same validation logic. It's ideal when you want to keep things concise.

    🍿 Example Usage

    Let’s create a few actors:

    var danyBoon = new FrenchActor("Dany Boon", 0);
    var isabelleHuppert = new FrenchActor("Isabelle Huppert", 2);
    var invalidActor = new FrenchActor("Unknown Star", -1); // Throws exception
    

    ✅ Summary

    🟣 Use a canonical constructor if you need full control and explicit field assignment.

    🟣 Prefer a compact constructor in records to keep the code clean and readable.

    🟣 Validation logic works identically in both.