• 🎬 Java Record Classes

    Featuring Famous French Actors

    In Java, record classes offer a concise, readable way to define immutable data structures—like casting actors for roles with a fixed script: no improvisation allowed!

    🧑‍🎤 Record Classes Are Final (Like Legendary Performances)

    Record classes are implicitly final. That means:

    🟣 You can’t extend them.

    🟣 But they can be generic, implement interfaces, and be annotated just like normal classes.

    Let’s explore these features using a cinematic theme.

    🌟 Example 1: A Generic Record – AwardedActor

    We want to record information about an actor and their Oscar prize. We'll make it generic to support different date formats.

    record AwardedActor<T extends Temporal>(
        String name,
        int numberOfOscars,
        T awardedDate
    ) { }
    
    🎭 Imagine:
    AwardedActor<LocalDate> marion = new AwardedActor<>("Marion Cotillard",
     1, 
    LocalDate.of(2008, 2, 24));

    Here, Marion Cotillard won her Oscar in 2008 for La Vie en Rose.
    We use generics to support different types of dates (LocalDate, ZonedDateTime, etc.).

    🎞️ Example 2: A Record Implementing an Interface – Actor implements Star

    We define a Star interface for anyone who shines on screen:

    interface Star {
        String catchPhrase();
    }

    Now let’s implement this in a record:

    record Actor(String name, int popularity) implements Star {
        @Override
        public String catchPhrase() {
            return "Lights, camera, " + name + "!";
        }
    }
    
    Example:
    Actor omar = new Actor("Omar Sy", 95);
    omar.catchPhrase() 👉 "Lights, camera, Omar Sy!"

    Even though records are compact, they can still carry behavior.

    🕰️ Example 3: Annotated Record – Movie

    We want to ensure our movies have a valid duration and a proper release date. Let's define a custom annotation:

    import java.lang.annotation.*;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    public @interface ValidDuration { }
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    public @interface NotInTheFuture { }

    Now let's define the Movie record:

    record Movie(
        String title,
        @NotInTheFuture LocalDate releaseDate,
        @ValidDuration int durationMinutes
    ) { }
    
    🎬 Example:
    new Movie("The Intouchables", LocalDate.of(2011, 11, 2), 112);

    What Does This Translate To Behind the Scenes?

    This annotated record:

    record Movie(@NotInTheFuture LocalDate releaseDate, @ValidDuration int durationMinutes) { }

    Is roughly equivalent to this normal class:

    public final class Movie {
        private final @NotInTheFuture LocalDate releaseDate;
        private final @ValidDuration int durationMinutes;
    
        public Movie(LocalDate releaseDate, int durationMinutes) {
            this.releaseDate = releaseDate;
            this.durationMinutes = durationMinutes;
        }
    
        public LocalDate releaseDate() { return this.releaseDate; }
        public int durationMinutes() { return this.durationMinutes; }
    }

    ➡️ The annotations apply to the fields thanks to @Target(ElementType.FIELD).

    🎯 Recap – Records with a Touch of Glamour