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 ?
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.- 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,staticousynchronized. - 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);
}
}
Constructeur appelé !
2. Types de constructeurs
2.1 Constructeur par défaut (sans paramètre)
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();
}
}
Constructeur par défaut appelé nom : null age : 0
class Exemple {
Exemple(int x) { }
}
Exemple e = new Exemple(); // Erreur de compilation
Exemple e = new Exemple(5); // Correct
2.2 Constructeur paramétré
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();
}
}
Constructeur paramétré appelé nom : ESSADDOUKI age : 32
3. Surcharge de constructeurs
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");
}
}
Constructeur (nom, age) Constructeur par défaut Constructeur (age, nom)
3.1 Appel d'un constructeur depuis un autre — this()
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");
}
}
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; (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));
}
}
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());
}
}
}
Étudiant créé : Mostafa Erreur : Le nom ne peut pas être vide
6. Exercice
Modéliser un livre avec constructeurs surchargés
Créer une classe Livre complète avec plusieurs constructeurs illustrant la surcharge et la délégation via this().
Travail demandé
- Déclarer les attributs :
String titre,String auteur,int annee,double prix. - 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.
- Déclarer une méthode
afficher()qui affiche toutes les informations du livre. - Tester les trois constructeurs dans le
main.
--- 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 €
public class Livre {
private String titre;
private String auteur;
private int annee;
private double prix;
public Livre(String titre, String auteur, int annee, double prix) {
this.titre = titre;
this.auteur = auteur;
this.annee = annee;
this.prix = prix;
}
public Livre(String titre, String auteur, int annee) {
this(titre, auteur, annee, 0.0);
}
public Livre(String titre, String auteur) {
this(titre, auteur, 2024, 0.0);
}
public void afficher() {
System.out.println("Titre : " + titre);
System.out.println("Auteur : " + auteur);
System.out.println("Année : " + annee);
System.out.println("Prix : " + prix + " €");
}
public static void main(String[] args) {
Livre l1 = new Livre("Clean Code", "Robert C. Martin", 2008, 35.0);
Livre l2 = new Livre("Effective Java", "Joshua Bloch", 2018);
Livre l3 = new Livre("Java 21", "Inconnu");
System.out.println("--- Livre 1 ---");
l1.afficher();
System.out.println("\n--- Livre 2 ---");
l2.afficher();
System.out.println("\n--- Livre 3 ---");
l3.afficher();
}
}
--- 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 €
- Délégation avec
this(): le constructeur à 3 paramètres appelle le constructeur à 4 paramètres avecprix = 0.0, et le constructeur à 2 paramètres appelle celui à 3 avecannee = 2024. Toute la logique d'initialisation est centralisée dans le constructeur complet. this()en première position : l'appel de délégation doit être la première instruction du constructeur — on ne peut pas écrire d'instructions avant.- Pas de type de retour : les constructeurs
Livre(...)n'ont pas devoidni d'autre type de retour — c'est ce qui les distingue syntaxiquement des méthodes.
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.