Les constructeurs en Java

09 Sep 2019 09 Sep 2019 34189 vues ESSADDOUKI Mostafa
Introduction
1 Nouveautés de Java 11 2 Différences entre JDK, JRE et JVM 3 Structure d'un programme Java - Hello World 4 Mots clés et conventions de dénomination en Java 5 Types de données intégrés en Java 6 Les variables en Java 7 Classes enveloppe - Number, Integer, Double ... 8 Lire les entrées clavier en Java
Structures de contrôle
9 Les opérateurs en Java 10 Les structures conditionnelles en Java 11 Les boucles en Java 12 Instructions de contrôle de boucle - break, continue
Chaines de caractères
13 Les chaines en Java - API String 14 Les chaines en Java - StringBuffer et StringBuilder 15 Les expressions régulières en Java
Programmation OO
16 Objets et classes en Java 17 Modificateurs d'accès Java - public, private, protected et package 18 Méthodes et surcharge des méthodes en Java 19 les constructeurs en Java 20 L'héritage en Java 21 Classes abstraites en Java 22 Interfaces et héritage multiple en Java 23 Les classes imbriquées en Java 24 Les singletons en Java 25 Classes et méthodes génériques 26 Interface fonctionnelle et expressions Lambda en Java
Tableaux et collections
27 Les tableaux en Java 28 Classe Arrays - java.util.Arrays 29 Les listes dynamiques - java.util.ArrayList 30 Les listes chaînées en Java - java.util.LinkedList 31 HashSet en Java - java.util.HashSet 32 HashMap en Java - java.util.HashMap
Gestion des fichiers
33 Comprendre les fichiers informatiques 34 Utilisation des classes Path et Files en Java 35 Lecture et écriture dans un fichier en Java 36 Fichiers à accès aléatoire en Java
Gestion d'exceptions
37 Gestion d'exceptions en Java 38 Créez vos propres classes d'exception en Java
Programmation concurrente
39 Introduction à la programmation concurrente en Java - Multi-threads 40 classe java.lang.Thread 41 Synchronisation des threads en Java

Les constructeurs en Java

  Prérequis

Maîtriser la déclaration de classes, d'attributs et de méthodes. Comprendre le mot-clé new et la notion d'instance. Connaître les modificateurs d'accès et le mot-clé this.

  Objectifs

Comprendre le rôle et les règles des constructeurs. Distinguer constructeur par défaut et constructeur paramétré. Maîtriser la surcharge de constructeurs. Différencier constructeur et méthode.

1. Qu'est-ce qu'un constructeur ?

Définition — Constructeur Un constructeur est un bloc de code spécial appelé automatiquement lors de la création d'un objet avec new. Son rôle est d'initialiser l'état de l'objet en affectant des valeurs initiales à ses attributs. Il porte obligatoirement le même nom que la classe et n'a pas de type de retour.
Règles de définition d'un constructeur
  • Le nom du constructeur doit être identique au nom de la classe.
  • Un constructeur ne déclare aucun type de retour (même pas void).
  • Les modificateurs d'accès (public, private…) peuvent s'appliquer.
  • Un constructeur ne peut pas être abstract, final, static ou synchronized.
  • Si aucun constructeur n'est défini, le compilateur génère automatiquement un constructeur par défaut (sans paramètre). Si un constructeur quelconque est défini, ce constructeur automatique n'est plus généré.

  Exemple 1 — Appel automatique du constructeur

public class Personne {
    private String nom;
    private int    age;

    public Personne(String nom, int age) {
        System.out.println("Constructeur appelé !");
        this.nom = nom;
        this.age = age;
    }

    public static void main(String[] args) {
        Personne p = new Personne("ESSADDOUKI", 32);
    }
}
Sortie
Constructeur appelé !

2. Types de constructeurs

2.1 Constructeur par défaut (sans paramètre)

Constructeur par défaut Un constructeur par défaut est un constructeur sans paramètre. Si aucun constructeur n'est explicitement déclaré dans la classe, le compilateur Java en génère un automatiquement. Ce constructeur implicite initialise les attributs à leurs valeurs par défaut : 0 pour les numériques, false pour les booléens, null pour les objets.

  Exemple 2 — Constructeur par défaut explicite

public class Personne {
    private String nom;
    private int    age;

    public Personne() {
        System.out.println("Constructeur par défaut appelé");
    }

    public void afficher() {
        System.out.println("nom : " + nom);
        System.out.println("age : " + age);
    }

    public static void main(String[] args) {
        Personne p = new Personne();
        p.afficher();
    }
}
Sortie
Constructeur par défaut appelé
nom : null
age : 0
Perte du constructeur par défaut implicite Dès qu'on déclare au moins un constructeur (avec ou sans paramètres), le compilateur ne génère plus le constructeur par défaut implicite. Pour continuer à instancier la classe sans arguments, il faut le déclarer explicitement.
class Exemple {
    Exemple(int x) { }
}

Exemple e = new Exemple();    // Erreur de compilation
Exemple e = new Exemple(5);   // Correct

2.2 Constructeur paramétré

Constructeur paramétré Un constructeur paramétré reçoit des arguments pour initialiser les attributs de l'objet avec des valeurs personnalisées dès sa création.

  Exemple 3 — Constructeur paramétré

public class Personne {
    private String nom;
    private int    age;

    public Personne(String nom, int age) {
        System.out.println("Constructeur paramétré appelé");
        this.nom = nom;
        this.age = age;
    }

    public void afficher() {
        System.out.println("nom : " + nom);
        System.out.println("age : " + age);
    }

    public static void main(String[] args) {
        Personne p = new Personne("ESSADDOUKI", 32);
        p.afficher();
    }
}
Sortie
Constructeur paramétré appelé
nom : ESSADDOUKI
age : 32

3. Surcharge de constructeurs

Surcharge de constructeurs Comme les méthodes, les constructeurs peuvent être surchargés : une même classe peut définir plusieurs constructeurs, à condition qu'ils aient des signatures différentes (nombre, types ou ordre des paramètres). Cela permet de créer des objets de différentes manières selon le contexte.

  Exemple 4 — Trois constructeurs surchargés

public class Personne {
    private String nom;
    private int    age;

    public Personne() {
        System.out.println("Constructeur par défaut");
    }

    public Personne(String nom, int age) {
        System.out.println("Constructeur (nom, age)");
        this.nom = nom;
        this.age = age;
    }

    public Personne(int age, String nom) {
        System.out.println("Constructeur (age, nom)");
        this.nom = nom;
        this.age = age;
    }

    public static void main(String[] args) {
        Personne p1 = new Personne("ESSADDOUKI", 32);
        Personne p2 = new Personne();
        Personne p3 = new Personne(32, "ESSADDOUKI");
    }
}
Sortie
Constructeur (nom, age)
Constructeur par défaut
Constructeur (age, nom)

3.1 Appel d'un constructeur depuis un autre — this()

this() — délégation de constructeur Dans un constructeur, l'appel this(...) permet d'appeler un autre constructeur de la même classe. Cela évite la duplication de code. L'appel this() doit obligatoirement être la première instruction du constructeur.

  Exemple 5 — Délégation avec this()

public class Produit {
    private String nom;
    private double prix;
    private int    stock;

    public Produit(String nom, double prix, int stock) {
        this.nom   = nom;
        this.prix  = prix;
        this.stock = stock;
        System.out.println("Produit créé : " + nom + " | " + prix + " € | stock : " + stock);
    }

    public Produit(String nom, double prix) {
        this(nom, prix, 0);
    }

    public Produit(String nom) {
        this(nom, 0.0, 0);
    }

    public static void main(String[] args) {
        Produit p1 = new Produit("Clavier", 49.99, 100);
        Produit p2 = new Produit("Souris", 29.99);
        Produit p3 = new Produit("Câble USB");
    }
}
Sortie
Produit créé : Clavier | 49.99 € | stock : 100
Produit créé : Souris | 29.99 € | stock : 0
Produit créé : Câble USB | 0.0 € | stock : 0

4. Constructeurs vs Méthodes

Critère Constructeur Méthode
Nom Identique au nom de la classe Librement choisi (lowerCamelCase)
Type de retour Aucun (pas même void) Type explicite ou void
Quand appelé ? Une seule fois, à la création de l'objet (new) Autant de fois que souhaité
Rôle principal Initialiser l'état de l'objet Exécuter un comportement
Peut être static ? Non Oui
Peut être abstract ? Non Oui
Surcharge ? Oui Oui
return dans un constructeur Bien qu'un constructeur ne déclare pas de type de retour, il est possible d'écrire return; (sans valeur) à l'intérieur pour quitter le constructeur prématurément — utile pour valider les paramètres.
public Personne(int age) {
    if (age < 0) {
        System.out.println("Âge invalide !");
        return;
    }
    this.age = age;
}

5. Cas particuliers importants

5.1 Constructeur privé — Singleton

Un constructeur private empêche toute instanciation depuis l'extérieur. C'est la base du patron de conception Singleton — une seule instance possible.

public class Singleton {
    private static Singleton instance = null;

    private Singleton() {
        System.out.println("Singleton créé");
    }

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }

    public static void main(String[] args) {
        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();
        System.out.println("Même instance ? " + (s1 == s2));
    }
}
Sortie
Singleton créé
Même instance ? true

5.2 Constructeur et validation des données

public class Etudiant {
    private String nom;
    private double moyenne;

    public Etudiant(String nom, double moyenne) {
        if (nom == null || nom.isBlank()) {
            throw new IllegalArgumentException("Le nom ne peut pas être vide");
        }
        if (moyenne < 0 || moyenne > 20) {
            throw new IllegalArgumentException("La moyenne doit être entre 0 et 20");
        }
        this.nom     = nom;
        this.moyenne = moyenne;
    }

    public static void main(String[] args) {
        Etudiant e1 = new Etudiant("Mostafa", 15.5);
        System.out.println("Étudiant créé : " + e1.nom);

        try {
            Etudiant e2 = new Etudiant("", 12.0);
        } catch (IllegalArgumentException ex) {
            System.out.println("Erreur : " + ex.getMessage());
        }
    }
}
Sortie
Étudiant créé : Mostafa
Erreur : Le nom ne peut pas être vide

6. Exercice

Modéliser un livre avec constructeurs surchargés

Niveau : Débutant

Créer une classe Livre complète avec plusieurs constructeurs illustrant la surcharge et la délégation via this().

Travail demandé

  1. Déclarer les attributs : String titre, String auteur, int annee, double prix.
  2. Déclarer les constructeurs suivants :
    • Livre(String titre, String auteur, int annee, double prix) — constructeur complet.
    • Livre(String titre, String auteur, int annee) — délègue au complet avec prix = 0.0.
    • Livre(String titre, String auteur) — délègue avec annee = 2024 et prix = 0.0.
  3. Déclarer une méthode afficher() qui affiche toutes les informations du livre.
  4. Tester les trois constructeurs dans le main.
Sortie attendue
Sortie
--- Livre 1 ---
Titre  : Clean Code
Auteur : Robert C. Martin
Année  : 2008
Prix   : 35.0 €

--- Livre 2 ---
Titre  : Effective Java
Auteur : Joshua Bloch
Année  : 2018
Prix   : 0.0 €

--- Livre 3 ---
Titre  : Java 21
Auteur : Inconnu
Année  : 2024
Prix   : 0.0 €

  L'essentiel en bref

Un constructeur initialise l'état d'un objet au moment de sa création avec new. Il porte le même nom que la classe et n'a aucun type de retour. Si aucun constructeur n'est déclaré, le compilateur génère un constructeur par défaut (sans paramètre) qui initialise les attributs à leurs valeurs par défaut (0, false, null). Dès qu'un constructeur est déclaré explicitement, ce constructeur automatique disparaît. Comme les méthodes, les constructeurs peuvent être surchargés — plusieurs constructeurs avec des signatures différentes offrent différentes façons d'instancier la classe. L'appel this(...) dans un constructeur délègue à un autre constructeur de la même classe et doit toujours être la première instruction. Un constructeur private empêche l'instanciation externe et est utilisé dans les patterns comme le Singleton.