Servono a inizializzare i valori dei campi degli oggetti.
Vengono invocati automaticamente dopo che l'oggetto è stato creato.
Questo tipo di costruzione mette dei valori iniziali nelle componenti:
Classe:
import java.awt.*; class NomeClasse { Point p; int x; }
Programma:
class ProvaCostr { public static void main(String args[]) { NomeClasse a; a=new NomeClasse(); System.out.println(a.p); System.out.println(a.x); } }
Stampa:
null 0
È possibile ridefinire il comportamento del costruttore.
import java.awt.*; class NomeClasse { Point p; int x; NomeClasse() { this.p=new Point(); this.p.move(10,20); this.x=100; } }
Uso lo stesso programma di prima:
class ProvaCostr { public static void main(String args[]) { NomeClasse a; a=new NomeClasse(); System.out.println(a.p); System.out.println(a.x); } }
Solo che ora stampa:
java.awt.Point[x=10,y=20] 100
class NomeClasse { ... NomeClasse() { istruzioni; } }
Si e no.
a=new NomeClasse();
Vengono fatte due cose:
Viene poi ritornato l'indirizzo della zona di memoria creata.
Questi costruttori sono già definiti:
p=new Point();
Crea un oggetto punto di coordinate (0,0)
p=new Point(12,32);
Crea un oggetto punto di coordinate (12,32)
Come tutti i metodi, i costruttori possono essere sovraccarichi (più costruttori con argomenti diversi).
Quando si invoca un metodo, viene fatta la copiatura dei parametri e poi si eseguono le istruzioni del metodo.
Nel caso dei costruttori, viene prima creato l'oggetto, e poi si esegue il costruttore come fosse un metodo.
C'è un passo in mezzo, in cui l'oggetto viene creato.
Il costruttore si usa per inizializzare le componenti degli oggetti.
Però può fare qualsiasi cosa fa un metodo.
Per esempio, può stampare una stringa:
class Abcd { int x; Point p; Abcd() { System.out.println("Questa e' una stringa"); } }
È sbagliato metodologicamente, ma si può fare.
Se una classe non ha costruttori, allora per essa viene automaticamente definito il costruttore vuoto.
Se in una classe ci metto un costruttore, allora quello vuoto non viene aggiunto automaticamente.
Se mi serve il costruttore vuoto, lo devo definire esplicitamente, in questo caso.
class Esempio1 { int x; }
Si può fare new Esempio1();
class Esempio2 { int x; Esempio2(int a) { this.x=a; } }
Si può fare new Esempio2(valore), ma non si può fare new Esempio2()
class Esempio3 { int x; Esempio3() { } Esempio3(int a) { this.x=a; } }
Si possono fare tutte e due le cose.
Fare cosí:
Di solito: gli argomenti sono i valori che vengono messi nelle componenti dell'oggetto creato (es. il costruttore di Studente qui sopra)
Qualche volta: sono dati che permettono di calcolare i valori iniziali dei campi dato
In generale: il costruttore è come tutti gli altri metodi (può fare quello che vuole con gli argomenti)
I costruttori non si ereditano.
Si possono riusare
Invocare un costruttore della sovraclasse: super
class Studente { Studente(String nome) { this.nome=nome; } class Borsista extends Studente { Borsista(String nome, int stipendio) { super(nome); this.stipendio=stipendio; } }
L'invocazione super(argomenti) equivale a invocare il costruttore della sovraclasse che ha questi argomenti
super(argomenti) deve essere la prima istruzione del costruttore di Borsista
Se la prima istruzione di un costruttore non è super(argomenti), si assume automaticamente che sia super()
class Studente { String nome; int anno; Studente() { this.nome="nessuno"; } } class Borsista extends Studente { }
Cosa stampa questo programma?
public static void main(String args[]) { Borsista s=new Borsista(); System.out.println(s.nome); }
La class Borsista non ha costruttori espliciti
Quindi ha il costruttore implicito:
Borsista() { }
Implicitamente, la prima istruzione di un costruttore è super():
Borsista() { super(); }
class Studente { String nome; int anno; Studente(String nome) { this.nome=nome; } } class Borsista extends Studente { }
Viene dato errore:
Borsista() { super(); }
Viene quindi dato errore.