Le constructeur en Java est utilisé pour créer une instance de la classe. Les constructeurs sont presque similaires aux méthodes, à l’exception de deux choses : leur nom est identique au nom de la classe et ils n’ont pas de type de retour. Parfois, les constructeurs sont également appelés méthodes spéciales pour initialiser un objet.
Constructeur en Java
Lorsque nous utilisons le mot clé « new » pour créer une instance d’une classe, le constructeur est invoqué et l’objet de la classe est retourné. Étant donné que le constructeur ne peut renvoyer que l’objet à la classe, cela est implicitement fait par l’exécution de Java et nous ne devons pas lui ajouter de type de retour. Si nous ajoutons un type de retour à un constructeur, il deviendra alors une méthode de la classe. C’est ainsi que l’exécution de Java distingue une méthode normale d’un constructeur. Supposons que nous ayons le code suivant dans la classe « Employee ».
public Employee() {
System.out.println("Employee Constructor");
}
public Employee Employee() {
System.out.println("Employee Method");
return new Employee();
}
Ici, le premier est un constructeur, remarquez qu’il n’y a pas de type de retour ni d’instruction de retour. Le deuxième est une méthode normale où nous appelons à nouveau le premier constructeur pour obtenir une instance d’employé et la renvoyer. Il est recommandé de ne pas avoir le même nom de méthode que le nom de la classe car cela crée de la confusion.
Types de constructeurs en Java
Il existe trois types de constructeurs en Java.
- Constructeur par défaut
- Constructeur sans argument
- Constructeur paramétré
Explorons tous ces types de constructeurs avec des programmes exemples.
Constructeur par défaut en Java
Il n’est pas toujours nécessaire de fournir une implémentation de constructeur dans le code de la classe. Si nous ne fournissons pas de constructeur, Java fournit une implémentation de constructeur par défaut que nous pouvons utiliser. Examinons un programme simple où le constructeur par défaut est utilisé car nous ne définirons pas explicitement de constructeur.
package com.journaldev.constructor;
public class Data {
public static void main(String[] args) {
Data d = new Data();
}
}
- Le rôle du constructeur par défaut est simplement d’initialiser l’objet et de le renvoyer au code appelant.
- Le constructeur par défaut est toujours sans argument et fourni par le compilateur Java uniquement lorsqu’aucun constructeur existant n’est défini.
- La plupart du temps, le constructeur par défaut nous convient car les autres propriétés peuvent être accédées et initialisées via les méthodes getter et setter.
Constructeur sans argument
Le constructeur sans argument est appelé un constructeur sans argument. C’est comme remplacer le constructeur par défaut et utilisé pour effectuer certaines opérations de pré-initialisation telles que la vérification des ressources, les connexions réseau, la journalisation, etc. Jetons un coup d’œil rapide au constructeur sans argument en java.
package com.journaldev.constructor;
public class Data {
// constructeur sans argument
public Data() {
System.out.println("No-Args Constructor");
}
public static void main(String[] args) {
Data d = new Data();
}
}
Maintenant lorsque nous appellerons new Data()
, alors notre constructeur sans argument sera appelé. L’image ci-dessous illustre ce comportement, vérifiez la sortie de la console du programme.
Constructeur paramétré
Le constructeur avec des arguments est appelé constructeur paramétré. Regardons l’exemple de constructeur paramétré en java.
package com.journaldev.constructor;
public class Data {
private String name;
public Data(String n) {
System.out.println("Parameterized Constructor");
this.name = n;
}
public String getName() {
return name;
}
public static void main(String[] args) {
Data d = new Data("Java");
System.out.println(d.getName());
}
}
Surcharge de constructeur en Java
Lorsque nous avons plus d’un constructeur, c’est une surcharge de constructeur en java. Regardons un exemple de surcharge de constructeur dans un programme java.
package com.journaldev.constructor;
public class Data {
private String name;
private int id;
// constructeur sans argument
public Data() {
this.name = "Default Name";
}
// constructeur à un paramètre
public Data(String n) {
this.name = n;
}
// constructeur à deux paramètres
public Data(String n, int i) {
this.name = n;
this.id = i;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
@Override
public String toString() {
return "ID="+id+", Name="+name;
}
public static void main(String[] args) {
Data d = new Data();
System.out.println(d);
d = new Data("Java");
System.out.println(d);
d = new Data("Pankaj", 25);
System.out.println(d);
}
}
Constructeur privé en Java
Remarquez que nous ne pouvons pas utiliser les mots-clés abstract, final, static et synchronized avec les constructeurs. Cependant, nous pouvons utiliser des modificateurs d’accès pour contrôler l’instanciation de l’objet de classe. Utiliser l’accès public
et default
est toujours possible, mais quel est l’intérêt de rendre un constructeur privé ? Dans ce cas, aucune autre classe ne pourra créer l’instance de la classe. Eh bien, un constructeur est rendu privé dans le cas où nous voulons implémenter le patron de conception singleton. Comme Java fournit automatiquement un constructeur par défaut, nous devons créer explicitement un constructeur et le garder privé. Les classes clientes disposent d’une méthode statique utilitaire pour obtenir l’instance de la classe. Un exemple de constructeur privé pour la classe Data
est donné ci-dessous.
// constructeur privé
private Data() {
// constructeur vide pour l'implémentation du modèle singleton
// peut contenir du code à utiliser à l'intérieur de la méthode getInstance() de la classe
}
Chaînage de constructeurs en Java
Lorsqu’un constructeur appelle un autre constructeur de la même classe, on parle de chaînage de constructeurs. Nous devons utiliser le mot-clé this
pour appeler un autre constructeur de la classe. Parfois, il est utilisé pour définir certaines valeurs par défaut des variables de classe. Notez qu’un autre appel de constructeur doit être la première instruction dans le bloc de code. De plus, il ne doit pas y avoir d’appels récursifs qui créeraient une boucle infinie. Voyons un exemple de chaînage de constructeurs dans un programme Java.
package com.journaldev.constructor;
public class Employee {
private int id;
private String name;
public Employee() {
this("John Doe", 999);
System.out.println("Default Employee Created");
}
public Employee(int i) {
this("John Doe", i);
System.out.println("Employee Created with Default Name");
}
public Employee(String s, int i) {
this.id = i;
this.name = s;
System.out.println("Employee Created");
}
public static void main(String[] args) {
Employee emp = new Employee();
System.out.println(emp);
Employee emp1 = new Employee(10);
System.out.println(emp1);
Employee emp2 = new Employee("Pankaj", 20);
System.out.println(emp2);
}
@Override
public String toString() {
return "ID = "+id+", Name = "+name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I have overridden the toString() method to print some useful information about Employee object. Below is the output produced by above program.
Employee Created
Default Employee Created
ID = 999, Name = John Doe
Employee Created
Employee Created with Default Name
ID = 10, Name = John Doe
Employee Created
ID = 20, Name = Pankaj
Remarquez comment un constructeur est appelé à partir d’un autre constructeur, c’est ce qu’on appelle le processus de chaînage de constructeurs.
Super Constructeur Java
Parfois, une classe hérite d’une superclasse, dans ce cas, si nous devons appeler le constructeur de la superclasse, nous pouvons le faire en utilisant le mot-clé super
. Regardons un exemple d’utilisation du constructeur de la superclasse. Notez que l’appel du constructeur super devrait être la première instruction dans le constructeur de la classe enfant. Lors de l’instanciation du constructeur de la classe enfant, Java initialise d’abord la superclasse, puis la classe enfant. Ainsi, si le constructeur de la superclasse n’est pas appelé explicitement, le constructeur par défaut ou sans argument est appelé par l’exécution Java. Comprendre ces concepts à travers un exemple de programme. Supposons que nous ayons deux classes comme ci-dessous.
package com.journaldev.constructor;
public class Person {
private int age;
public Person() {
System.out.println("Person Created");
}
public Person(int i) {
this.age = i;
System.out.println("Person Created with Age = " + i);
}
}
package com.journaldev.constructor;
public class Student extends Person {
private String name;
public Student() {
System.out.println("Student Created");
}
public Student(int i, String n) {
super(i); // super class constructor called
this.name = n;
System.out.println("Student Created with name = " + n);
}
}
Maintenant, si nous créons un objet Student comme ci-dessous;
Student st = new Student();
Quelle sera la sortie produite? La sortie du code ci-dessus sera:
Person Created
Student Created
Ainsi, l’appel s’est dirigé vers le constructeur sans argument de la classe Student car il n’y avait pas d’appel super dans la première instruction, le constructeur par défaut de la classe Personne est appelé. D’où la sortie. Que se passe-t-il si nous utilisons le constructeur paramétré de la classe Student comme Student st = new Student(34, "Pankaj");
, la sortie sera:
Person Created with Age = 34
Student Created with name = Pankaj
Ici, la sortie est claire car nous appelons explicitement le constructeur de la superclasse, donc Java n’a pas besoin de faire de travail supplémentaire de leur côté.
Constructeur de copie Java
Le constructeur de copie Java prend l’objet de la même classe comme argument et crée une copie de celui-ci. Parfois, nous avons besoin d’une copie d’un autre objet pour effectuer un traitement. Nous pouvons le faire de plusieurs manières :
- implémenter le clonage
- fournir une méthode utilitaire pour la copie profonde de l’objet.
- Avoir un constructeur de copie
Maintenant, voyons comment écrire un constructeur de copie. Supposons que nous ayons une classe Fruits
comme ci-dessous.
package com.journaldev.constructor;
import java.util.ArrayList;
import java.util.List;
public class Fruits {
private List<String> fruitsList;
public List<String> getFruitsList() {
return fruitsList;
}
public void setFruitsList(List<String> fruitsList) {
this.fruitsList = fruitsList;
}
public Fruits(List<String> fl) {
this.fruitsList = fl;
}
public Fruits(Fruits fr) {
List<String> fl = new ArrayList<>();
for (String f : fr.getFruitsList()) {
fl.add(f);
}
this.fruitsList = fl;
}
}
Remarquez que Fruits(Fruits fr)
effectue une copie profonde pour retourner la copie de l’objet. Examinons un programme de test pour comprendre pourquoi il est préférable d’avoir un constructeur de copie pour copier un objet.
package com.journaldev.constructor;
import java.util.ArrayList;
import java.util.List;
public class CopyConstructorTest {
public static void main(String[] args) {
List<String> fl = new ArrayList<>();
fl.add("Mango");
fl.add("Orange");
Fruits fr = new Fruits(fl);
System.out.println(fr.getFruitsList());
Fruits frCopy = fr;
frCopy.getFruitsList().add("Apple");
System.out.println(fr.getFruitsList());
frCopy = new Fruits(fr);
frCopy.getFruitsList().add("Banana");
System.out.println(fr.getFruitsList());
System.out.println(frCopy.getFruitsList());
}
}
Le résultat du programme ci-dessus est :
[Mango, Orange]
[Mango, Orange, Apple]
[Mango, Orange, Apple]
[Mango, Orange, Apple, Banana]
Remarquez que lorsque le constructeur de copie est utilisé, l’objet original et sa copie sont indépendants l’un de l’autre et toute modification dans l’un d’eux ne se reflétera pas dans l’autre. C’est tout pour le constructeur en java.
Source:
https://www.digitalocean.com/community/tutorials/constructor-in-java