Java Language
Costruttori
Ricerca…
introduzione
Sebbene non richiesti, i costruttori in Java sono metodi riconosciuti dal compilatore per creare istanze di valori specifici per la classe che possono essere essenziali per il ruolo dell'oggetto. Questo argomento dimostra l'uso corretto dei costruttori di classi Java.
Osservazioni
La specifica del linguaggio Java parla a lungo della natura esatta della semantica del costruttore. Possono essere trovati in JLS §8.8
Costruttore predefinito
Il "default" per i costruttori è che non hanno argomenti. Nel caso in cui non si specifica alcun costruttore, il compilatore genererà per te un costruttore predefinito.
Ciò significa che i seguenti due snippet sono semanticamente equivalenti:
public class TestClass {
private String test;
}
public class TestClass {
private String test;
public TestClass() {
}
}
La visibilità del costruttore predefinito è la stessa della visibilità della classe. Quindi un pacchetto definito dalla classe ha un costruttore predefinito privato del pacchetto
Tuttavia, se hai un costruttore non predefinito, il compilatore non genererà per te un costruttore predefinito. Quindi questi non sono equivalenti:
public class TestClass {
private String test;
public TestClass(String arg) {
}
}
public class TestClass {
private String test;
public TestClass() {
}
public TestClass(String arg) {
}
}
Fare attenzione che il costruttore generato non esegue l'inizializzazione non standard. Ciò significa che tutti i campi della classe avranno il loro valore predefinito, a meno che non abbiano un inizializzatore.
public class TestClass {
private String testData;
public TestClass() {
testData = "Test"
}
}
I costruttori sono chiamati così:
TestClass testClass = new TestClass();
Costruttore con argomenti
I costruttori possono essere creati con qualsiasi tipo di argomento.
public class TestClass {
private String testData;
public TestClass(String testData) {
this.testData = testData;
}
}
Chiamato in questo modo:
TestClass testClass = new TestClass("Test Data");
Una classe può avere più costruttori con diverse firme. Per concatenare le chiamate del costruttore (chiamare un costruttore diverso della stessa classe durante l'istanziazione) usare this()
.
public class TestClass {
private String testData;
public TestClass(String testData) {
this.testData = testData;
}
public TestClass() {
this("Test"); // testData defaults to "Test"
}
}
Chiamato in questo modo:
TestClass testClass1 = new TestClass("Test Data");
TestClass testClass2 = new TestClass();
Chiama il costruttore genitore
Supponiamo che tu abbia una classe Parent e una classe Child. Per costruire un'istanza Child, è necessario sempre un costruttore Parent da eseguire nella gebinning del costruttore Child. Possiamo selezionare il costruttore principale che vogliamo chiamando esplicitamente super(...)
con gli argomenti appropriati come la nostra prima istruzione del costruttore Child. Questo ci fa risparmiare tempo riutilizzando il costruttore delle classi Parent invece di riscrivere lo stesso codice nel costruttore delle classi Child.
Senza metodo super(...)
:
(implicitamente, la versione no-args super()
è chiamata invisibilmente)
class Parent {
private String name;
private int age;
public Parent() {} // necessary because we call super() without arguments
public Parent(String tName, int tAge) {
name = tName;
age = tAge;
}
}
// This does not even compile, because name and age are private,
// making them invisible even to the child class.
class Child extends Parent {
public Child() {
// compiler implicitly calls super() here
name = "John";
age = 42;
}
}
Con il metodo super()
:
class Parent {
private String name;
private int age;
public Parent(String tName, int tAge) {
name = tName;
age = tAge;
}
}
class Child extends Parent {
public Child() {
super("John", 42); // explicit super-call
}
}
Nota: le chiamate a un altro costruttore (concatenamento) o al super costruttore DEVONO essere la prima istruzione all'interno del costruttore.
Se si chiama esplicitamente il costruttore super(...)
, deve esistere un costruttore genitore corrispondente (è semplice, non è vero?).
Se non si richiama esplicitamente alcun costruttore super(...)
, la classe genitore deve avere un costruttore no-args e questo può essere scritto esplicitamente o creato come predefinito dal compilatore se la classe genitore non fornisce qualsiasi costruttore.
class Parent{
public Parent(String tName, int tAge) {}
}
class Child extends Parent{
public Child(){}
}
La classe Parent non ha un costruttore predefinito, quindi il compilatore non può aggiungere super
nel costruttore Child. Questo codice non verrà compilato. Devi cambiare i costruttori per adattarli a entrambi i lati, o scrivere la tua super
chiamata, in questo modo:
class Child extends Parent{
public Child(){
super("",0);
}
}