2. Costruttori
Costruttore di default
Se non viene fornito nessun costruttore, il compilatore ne crea uno di default senza parametri, che:
- Alloca lo spazio per gli attributi di tipo primitivo
- Alloca lo spazio per i riferimenti agli attributi definiti dall’utente
- Inizializza tutti i riferimenti a null, tutte le variabili numeriche a 0 e tutti i booleani a false.
Se invece viene fornito un costruttore da parte del programmatore, il compilatore non fornisce quello di default.
public class C{
private int i1;
private int i2;
}
public class Example{
public static void main(String args[]){
C c;
x = new C(); // OK: non c'è nessun costruttore, quindi il compilatore assegna quello di default
x = new C(5, 7); // Errore di compilazione: non c'è nessun costruttore che prende 2 parametri
}
}
Costruttore custom
public class C{
private int i1;
private int i2;
public C(int a1, int a2){
i1 = a1;
i2 = a2;
}
public C(int a){
i1 = a;
i2 = a;
}
}
public class Example{
public static void main(String args[]){
C x, y, z;
x = new C(); // Errore: visto che sono stati forniti 2 costruttori, quello di default non viene creato
y = new C(1); // OK: viene usato il secondo
z = new C(1,4); // OK: viene usato il primo
}
}
Più costruttori possono essere definiti in una classe, basta che abbiano un diverso numero di parametri.
Costruttori innestati
È possibile invocare un costruttore dentro ad un altro con la notazione this(<lista_di_parametri_del_costruttore)
.
Nel caso in cui si facesse una cosa del genere, la chiamata al costruttore deve essere la prima cosa che viene eseguita all’interno del costruttore chiamante.
public Date(int g, int m, int a){
if (validDate(g,m,a)) { // validDate is a static method
day = g; month = m; year = a;
}
else ...
}
public Date(int g, int m) { //day and month + year by default
this(g,m,1900);
}
Assegnamento
L’operatore assegnamento ‘=’ quando applicato a:
- Variabili ed espressioni di tipi di dati primitivi: copia il valore
- Variabili ed espressioni di tipi di dati referenziato: copia il riferimento, non il valore.
Ex.
Date d1, d2;
d2 = new Date(1, 2, 2004);
d1 = d2;
Dopo l’esecuzione della terza riga, d1
e d2
contengono il riferimento allo stesso oggetto (puntano allo stesso oggetto).
NB: L’assegnamento tra due oggetti viene considerato come errore a compile time se i tipi statici non sono uguali.
Condivisione (aliasing)
Si ha quando un oggetto è condiviso tra due variabili che possono accedervi.
L’assegnamento di variabili di tipo referenziato, come nell’esempio precedente, genera condivisione.
Se l’oggetto condiviso è modificabile, i cambiamenti fatti attraverso una variabile sono visibili anche tramite l’altra.
Riferimenti e operatore ==
L’operatore di confronto ‘==’ confronta i valori di riferimento, non gli oggetti!
Date d1 = new Date(1, 12, 2001);
Date d2 = new Date(1, 12, 2001);
if(d1 == d2){
System.out.println("True");
} else {
System.out.println("False");
}
Quando si esegue questo codice, viene stampato a schermo “False”, siccome, nonostante i valori degli attributi di d1
e d2
siano uguali, essi sono due oggetti distinti e quindi hanno due diversi riferimenti a livello di memoria.
Confronto di uguaglianza
Il metodo equals()
permette di controllare se due oggetti sono uguali, cioè controlla se il valore dei loro attributi è uguale.
Ex.
String a = new String("Alberto");
String b = new String("Hallo");
String c = new String("Hallo");
if(a.equals(c)); // False
if(b.equals(c)); // True
if(b == c); // False
Stringhe
Le stringhe sono elementi immutabili: non è possibile aggiungere o rimuovere carattere ad una stringa, ma per farlo occorre allocare una nuova stringa.
Costruttori: String()
e String(String s)
.
Operatore di concatenazione: +
Qualche metodo pubblico:
int lenght()
, ritorna la lunghezza della stringa
char charAt(int index)
, ritorna il carattere alla posizione specificata daindex
String subString(int beginIndex)
, inizia da 0
Chiamata di un metodo
- Vengono valutati i parametri
- Viene creato sulla stack il record di attivazione
- Allocato lo spazio per i parametri formali
- Allocato lo spazio per le variabili locali
- Viene eseguito il corpo del metodo
Regole per il passaggio dei parametri:
- I parametri di tipo semplice vengono passati con copia
- I parametri di tipo referenziato vengono passati con riferimento
Metodo clone()
Il metodo clone è un metodo protetto definito nella classe Object
e ritorna una copia di un oggetto.
Per usare questo metodo bisogna implementare nella classe dove viene usato l’interfaccia Clonable
.