Il costruttore in Java viene utilizzato per creare un’istanza della classe. I costruttori sono simili ai metodi tranne per due cose: il loro nome è lo stesso della classe e non hanno un tipo di ritorno. A volte i costruttori vengono anche definiti come metodi speciali per inizializzare un oggetto.
Costruttore in Java
Ogni volta che utilizziamo la parola chiave “new” per creare un’istanza di una classe, viene invocato il costruttore e viene restituito l’oggetto della classe. Poiché il costruttore può solo restituire l’oggetto alla classe, viene implicitamente eseguito da Java Runtime e non è necessario aggiungere un tipo di ritorno ad esso. Se aggiungiamo un tipo di ritorno a un costruttore, diventerà un metodo della classe. Questo è il modo in cui Java Runtime distingue tra un metodo normale e un costruttore. Supponiamo di avere il seguente codice nella classe “Employee”.
public Employee() {
System.out.println("Employee Constructor");
}
public Employee Employee() {
System.out.println("Employee Method");
return new Employee();
}
Qui il primo è un costruttore, notate che non c’è un tipo di ritorno e nessuna istruzione di ritorno. Il secondo è un metodo normale in cui richiamiamo nuovamente il primo costruttore per ottenere un’istanza di “Employee” e restituirla. È consigliabile non avere lo stesso nome del metodo della classe perché crea confusione.
Tipi di costruttori in Java
Ci sono tre tipi di costruttori in Java.
- Costruttore predefinito
- Costruttore senza argomenti
- Costruttore parametrizzato
Esaminiamo tutti questi tipi di costruttori con esempi di programmi.
Costruttore predefinito in Java
Non è sempre necessario fornire un’implementazione del costruttore nel codice della classe. Se non forniamo un costruttore, allora Java fornisce un’implementazione di costruttore predefinita per noi da utilizzare. Esaminiamo un semplice programma in cui viene utilizzato il costruttore predefinito poiché non definiremo esplicitamente un costruttore.
package com.journaldev.constructor;
public class Data {
public static void main(String[] args) {
Data d = new Data();
}
}
- Il ruolo unico del costruttore predefinito è quello di inizializzare l’oggetto e restituirlo al codice chiamante.
- Il costruttore predefinito è sempre senza argomenti e viene fornito dal compilatore Java solo quando non è definito alcun costruttore esistente.
- La maggior parte delle volte ci accontentiamo del costruttore predefinito stesso poiché altre proprietà possono essere accessibili e inizializzate tramite i metodi getter setter.
Costruttore senza argomenti
Costruttore senza alcun argomento è chiamato costruttore senza argomenti. È come sovrascrivere il costruttore predefinito e viene utilizzato per fare alcune operazioni di pre-inizializzazione come il controllo delle risorse, le connessioni di rete, la registrazione, ecc. Diamo un’occhiata rapida al costruttore senza argomenti in Java.
package com.journaldev.constructor;
public class Data {
//costruttore senza argomenti
public Data() {
System.out.println("No-Args Constructor");
}
public static void main(String[] args) {
Data d = new Data();
}
}
Ora quando chiameremo new Data()
, verrà chiamato il nostro costruttore senza argomenti. L’immagine sottostante illustra questo comportamento, controlla l’output della console del programma.
Costruttore Parametrizzato
Costruttore con argomenti è chiamato costruttore parametrizzato. Vediamo l’esempio di costruttore parametrizzato in 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());
}
}
So sovraccarico costruttore in Java
Quando abbiamo più di un costruttore, allora è sovraccarico di costruttore in Java. Vediamo un esempio di sovraccarico di costruttore in un programma Java.
package com.journaldev.constructor;
public class Data {
private String name;
private int id;
//costruttore senza argomenti
public Data() {
this.name = "Default Name";
}
//costruttore a un parametro
public Data(String n) {
this.name = n;
}
//costruttore a due parametri
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);
}
}
Costruttore Privato in Java
Nota che non possiamo utilizzare le parole chiave abstract, final, static e synchronized con i costruttori. Tuttavia, possiamo utilizzare i modificatori di accesso per controllare l’istanziazione dell’oggetto della classe. Utilizzare gli accessi public
e default
è comunque accettabile, ma qual è l’uso di rendere un costruttore privato? In quel caso, nessun’altra classe sarà in grado di creare l’istanza della classe. Beh, un costruttore viene reso privato nel caso in cui vogliamo implementare il pattern di progettazione singleton. Dal momento che Java fornisce automaticamente un costruttore predefinito, dobbiamo esplicitamente creare un costruttore e mantenerlo privato. Le classi client vengono fornite con un metodo statico di utilità per ottenere l’istanza della classe. Di seguito è riportato un esempio di costruttore privato per la classe Data
.
// costruttore privato
private Data() {
// costruttore vuoto per l'implementazione del pattern singleton
// può contenere il codice da utilizzare all'interno del metodo getInstance() della classe
}
Costruzione del costruttore in Java
Quando un costruttore chiama un altro costruttore della stessa classe, si chiama catena di costruttori. Dobbiamo utilizzare la parola chiave this
per chiamare un altro costruttore della classe. A volte viene utilizzato per impostare alcuni valori predefiniti delle variabili di classe. Nota che la chiamata di un altro costruttore dovrebbe essere la prima istruzione nel blocco di codice. Inoltre, non dovrebbero esserci chiamate ricorsive che creerebbero un loop infinito. Vediamo un esempio di catena di costruttori in un programma 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
Nota come un costruttore viene chiamato da un altro costruttore, questo è chiamato processo di catena di costruttori.
Costruttore Super Java
A volte una classe eredita da una superclasse, in quel caso, se dobbiamo chiamare il costruttore della superclasse allora possiamo farlo usando la parola chiave super
. Diamo un’occhiata a un esempio di utilizzo del costruttore della superclasse. Nota che la chiamata al costruttore super dovrebbe essere la prima istruzione nel costruttore della classe figlio. Inoltre, quando si istanzia il costruttore della classe figlio, Java inizializza prima la superclasse e poi la classe figlio. Quindi, se il costruttore della superclasse non viene chiamato esplicitamente, viene chiamato il costruttore predefinito o senza argomenti da parte del runtime di Java. Capiamo questi concetti attraverso alcuni esempi di programma. Supponiamo di avere due classi come di seguito.
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);
}
}
Ora se creiamo un oggetto Student come di seguito;
Student st = new Student();
Qual sarà l’output prodotto? L’output del codice sopra sarà:
Person Created
Student Created
Quindi la chiamata è andata al costruttore senza argomenti della classe Student poiché non c’era alcuna chiamata super nella prima istruzione, viene chiamato il costruttore predefinito o senza argomenti della classe Person. Perciò l’output. Cosa succede se stiamo usando il costruttore con parametri della classe Student come Student st = new Student(34, "Pankaj");
, l’output sarà:
Person Created with Age = 34
Student Created with name = Pankaj
Qui l’output è chiaro perché stiamo chiamando esplicitamente il costruttore della superclasse, quindi Java non ha bisogno di fare alcun lavoro extra da parte loro.
Costruttore di copia Java
Il costruttore di copia di Java prende l’oggetto della stessa classe come argomento e ne crea una copia. A volte abbiamo bisogno di una copia di un altro oggetto per effettuare qualche elaborazione. Possiamo farlo in diversi modi:
- implementando clonazione
- fornendo un metodo di utilità per la copia profonda dell’oggetto.
- Avere un costruttore di copia
Ora vediamo come scrivere un costruttore di copia. Supponiamo di avere una classe Fruits
come segue.
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;
}
}
Si noti che Fruits(Fruits fr)
sta effettuando una copia profonda per restituire la copia dell’oggetto. Vediamo un programma di test per capire perché è meglio avere un costruttore di copia per copiare un oggetto.
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());
}
}
L’output del programma precedente è:
[Mango, Orange]
[Mango, Orange, Apple]
[Mango, Orange, Apple]
[Mango, Orange, Apple, Banana]
Si noti che quando viene utilizzato il costruttore di copia, l’oggetto originale e la sua copia non sono correlati tra loro e le modifiche in uno di essi non si rifletteranno nell’altro. Questo è tutto per il costruttore in Java.
Source:
https://www.digitalocean.com/community/tutorials/constructor-in-java