0Pricing
Java Academy · Leçon

Constructeurs compacts et validation

Ajoutez une logique de validation dans les constructeurs compacts afin de garantir l’intégrité des données.

Constructeurs compacts et validation est une leçon Java Academy gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Java Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Java Academy comprend 4 leçons au total.

Constructeurs compacts

Un constructeur compact dans un enregistrement s’exécute avant l’affectation des composants. Il permet de valider ou de normaliser les données sans répéter les affectations des composants.

Constructeur standard ou compact

Le constructeur canonique standard affecte explicitement les composants. Le constructeur compact omet la liste des paramètres et les affectations : celles-ci sont effectuées automatiquement après l’exécution du corps.

// Standard canonical constructor
record Range(int min, int max) {
    Range(int min, int max) {
        if (min > max) throw new IllegalArgumentException("min > max");
        this.min = min;  // explicit assignment
        this.max = max;
    }
}

// Compact constructor (same behavior, less code)
record Range2(int min, int max) {
    Range2 {  // no parameter list, no assignments
        if (min > max) throw new IllegalArgumentException("min > max");
        // components are assigned automatically after this block
    }
}

Validation dans les constructeurs compacts

Les constructeurs compacts constituent la manière standard de valider les données d’un enregistrement. Lancez rapidement des exceptions pour faire respecter les invariants.

record Email(String address) {
    Email {
        if (address == null || address.isBlank())
            throw new IllegalArgumentException("Email cannot be blank");
        if (!address.contains("@"))
            throw new IllegalArgumentException("Invalid email: " + address);
        address = address.toLowerCase().strip(); // normalize (Java 16+)
    }
}

Email e = new Email("  Alice@Example.com  ");
System.out.println(e.address()); // alice@example.com

try { new Email("not-an-email"); }
catch (IllegalArgumentException ex) { System.out.println(ex.getMessage()); }

Normalisation dans les constructeurs compacts

Vous pouvez modifier les variables des composants dans un constructeur compact avant leur affectation. Cela normalise les données lors de la construction.

record PersonName(String firstName, String lastName) {
    PersonName {
        firstName = capitalize(firstName);
        lastName  = capitalize(lastName);
    }

    private static String capitalize(String s) {
        if (s == null || s.isEmpty()) return s;
        return Character.toUpperCase(s.charAt(0)) +
               s.substring(1).toLowerCase();
    }

    public String fullName() { return firstName + " " + lastName; }
}

PersonName name = new PersonName("jOHN", "DOE");
System.out.println(name.fullName()); // John Doe

Copies défensives

Pour les composants mutables tels que les tableaux ou les collections, effectuez une copie défensive dans le constructeur compact afin de préserver l’immuabilité.

import java.util.*;

record Snapshot(List<String> items) {
    Snapshot {
        items = List.copyOf(items); // defensive copy — unmodifiable
    }
}

List<String> mutable = new ArrayList<>(List.of("a", "b", "c"));
Snapshot snap = new Snapshot(mutable);
mutable.add("d"); // doesn't affect snapshot
System.out.println(snap.items()); // [a, b, c]

try {
    snap.items().add("e"); // UnsupportedOperationException
} catch (UnsupportedOperationException e) {
    System.out.println("Snapshot is truly immutable!");
}

Enregistrement Range avec bornes

Un enregistrement Range pratique qui garantit min <= max et fournit des méthodes utilitaires utiles.

record Range(int min, int max) {
    Range {
        if (min > max) throw new IllegalArgumentException(
            "min (" + min + ") must be <= max (" + max + ")");
    }

    public boolean contains(int value) { return value >= min && value <= max; }
    public int size()  { return max - min; }
    public int clamp(int value) { return Math.max(min, Math.min(max, value)); }
}

Range valid = new Range(1, 10);
System.out.println(valid.contains(5));  // true
System.out.println(valid.clamp(15));    // 10
System.out.println(valid.size());       // 9

Enchaîner la logique du constructeur compact

Pour les validations complexes, extrayez des méthodes auxiliaires et appelez-les depuis le constructeur compact.

record CreditCard(String number, String cvv, int expiryMonth, int expiryYear) {
    CreditCard {
        validateNumber(number);
        validateCvv(cvv);
        validateExpiry(expiryMonth, expiryYear);
        number = number.replaceAll("[^0-9]", ""); // strip spaces/dashes
    }

    private static void validateNumber(String n) {
        String digits = n.replaceAll("[^0-9]", "");
        if (digits.length() < 13 || digits.length() > 19)
            throw new IllegalArgumentException("Invalid card number length");
    }
    private static void validateCvv(String cvv) {
        if (!cvv.matches("[0-9]{3,4}"))
            throw new IllegalArgumentException("Invalid CVV");
    }
    private static void validateExpiry(int m, int y) {
        if (m < 1 || m > 12) throw new IllegalArgumentException("Invalid month");
        if (y < 2024)         throw new IllegalArgumentException("Card expired");
    }
}

Plusieurs motifs de constructeurs compacts

Motifs courants de validation utilisés dans les constructeurs compacts.

record Percentage(double value) {
    Percentage {
        if (value < 0 || value > 100)
            throw new IllegalArgumentException(
                "Percentage must be 0-100, got: " + value);
        value = Math.round(value * 100.0) / 100.0; // round to 2 dp
    }

    public double asFraction() { return value / 100.0; }
}

Percentage tax = new Percentage(8.756);
System.out.println(tax.value());       // 8.76
System.out.println(tax.asFraction()); // 0.0876

Constructeurs non canoniques

Les enregistrements peuvent avoir des constructeurs supplémentaires, mais ceux-ci doivent déléguer au constructeur canonique au moyen de this(...).

record Point(double x, double y) {
    // Non-canonical constructor: origin point
    Point() { this(0.0, 0.0); }

    // Non-canonical: polar coordinates
    static Point fromPolar(double r, double theta) {
        return new Point(r * Math.cos(theta), r * Math.sin(theta));
    }

    public double distance(Point other) {
        double dx = this.x - other.x;
        double dy = this.y - other.y;
        return Math.sqrt(dx*dx + dy*dy);
    }
}

Point origin = new Point();
Point p = Point.fromPolar(5, Math.PI/4);
System.out.printf("Distance: %.2f%n", origin.distance(p)); // 5.00

Enregistrement de collection immuable

Un enregistrement contenant un instantané immuable des préférences utilisateur, qui valide et normalise les données lors de la construction.

import java.util.*;

record UserPreferences(String theme, Set<String> enabledFeatures, int fontSize) {
    private static final Set<String> VALID_THEMES = Set.of("light", "dark", "system");
    private static final Set<String> VALID_FEATURES = Set.of("ai", "beta", "analytics");

    UserPreferences {
        if (!VALID_THEMES.contains(theme))
            throw new IllegalArgumentException("Unknown theme: " + theme);
        if (!VALID_FEATURES.containsAll(enabledFeatures))
            throw new IllegalArgumentException("Unknown feature in: " + enabledFeatures);
        if (fontSize < 10 || fontSize > 24)
            throw new IllegalArgumentException("fontSize must be 10-24");
        enabledFeatures = Set.copyOf(enabledFeatures); // defensive copy
    }
}

Limites des constructeurs compacts

Voici ce que vous ne pouvez pas faire dans un constructeur compact :

  • Vous ne pouvez pas affecter explicitement les composants (ils sont affectés automatiquement après l’exécution du bloc)
  • Vous ne pouvez pas appeler this() ou super()
  • Le fait de lancer une exception empêche toute affectation des composants
record Safe(int value) {
    Safe {
        // CAN: validate and modify component variables
        if (value < 0) value = 0; // normalized to 0 if negative
        // value = this.value; // NOT NEEDED — assignment happens after block
    }
}

System.out.println(new Safe(-5).value());  // 0 (normalized)
System.out.println(new Safe(10).value());  // 10

Vérification rapide

Dans un constructeur compact, que deviennent les modifications apportées aux variables des composants ?

Récapitulatif : constructeurs compacts et validation

À retenir :

  • Les constructeurs compacts s’exécutent avant l’affectation des composants : aucune affectation explicite n’est nécessaire
  • Utilisez-les pour valider, normaliser ou copier les composants de manière défensive
  • Modifiez les variables des composants pour normaliser les valeurs (passage en minuscules, suppression des espaces ou copie)
  • Lancez IllegalArgumentException pour les données invalides afin de faire respecter les invariants
  • Utilisez List.copyOf / Set.copyOf pour les composants de collection mutables
  • Les constructeurs non canoniques doivent déléguer au constructeur canonique

Questions Fréquemment Posées

La leçon « Constructeurs compacts et validation » est-elle gratuite ?

Oui — le texte complet de « Constructeurs compacts et validation » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Java Academy, passe à CoddyKit PRO. Le cours Java Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Constructeurs compacts et validation » ?

Ajoutez une logique de validation dans les constructeurs compacts afin de garantir l’intégrité des données. Tu pratiques Java Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Java Academy ?

Aucune expérience préalable n'est requise. Java Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.

Combien de temps prend la leçon « Constructeurs compacts et validation » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Java Academy ?

Oui. Chaque leçon Java Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Découvrir les records
  2. Constructeurs compacts et validation
  3. Méthodes personnalisées dans les records
  4. Records, classes et Lombok
← Retour à Java Academy