5 Passaggio dei parametri e inizializzazione di oggetti
In Java il passaggio dei parametri è per valore, ovvero all’atto della chiamata di un metodo viene creata una copia del parametro attuale che è assegnata al parametro formale.
public class PassReferences {
static void f(int i) {
++;
iSystem.out.println(i);
}
public static void main(String[] args) {
int x = 0;
System.out.println(x);
f(x);
System.out.println(x);
}
}
/* Output:
0
1
0
*/
class Index {
int i;
}
public class PassReferences {
static void f(Index index) {
// x viene copiato e reso disponibile a f mediante index, ma x è il riferimento ad un oggetto, quindi index è uguale al riferimento dell'oggetto, pertanto se lo vado a modificare, questa modifica si rifletterà anche al termine dello scope di f perchè ho modificato la stessa area di memoria
.i++;
indexSystem.out.println(index.i);
}
public static void main(String[] args) {
= new Index();
Index x System.out.println(x.i);
f(x);
System.out.println(x.i);
}
}
/* Output:
0
1
1
*/
6 Clonazione
In Java è possibile clonare un oggetto attraverso il metodo clone(), un metodo protected della classe Object.
Il metodo clone() genera un Object a cui deve essere applicato il casting al proprio tipo.
Se si vuole rendere una classe clonabile è necessario:
che la classe implementi l’interfaccia Cloneable
creare un proprio metodo clone() per la classe rendendolo public;
import java.util.*;
class MyObject implements Cloneable {
private int i;
MyObject(int ii) {
= ii;
i }
public Object clone() {
Object o = null;
try {
= super.clone();
o } catch(CloneNotSupportedException e) {
System.err.println("MyObject can't clone");
}
return o;
}
public String toString() {
return Integer.toString(i);
}
}
class MyObject2 implements Cloneable {
private MyObject i; // Anche le classi coinvolte nella composizione devono essere Cloneable
MyObject2 (MyObject ii) {
= ii;
i }
public Object clone() {
Object o = null;
try {
= super.clone();
o } catch(CloneNotSupportedException e) {
System.err.println("MyObject2 can't clone");
}
return o;
}
}
6.1 Classi a sola lettura
Java permette di creare delle classi a sola-lettura i cui oggetti sono immutabili.
Esempi di classe read-only sono le classi wrapper dei tipi primitivi.
import java.util.*;
public class ImmutableInteger {
public static void main(String[] args) {
Integer v[] = new Integer[10];
for(int i = 0; i < 10; i++) {
[i] = new Integer(i);
v}
for(int i = 0; i < 10; i++) {
[i]++; // equivale a v[i] = new Integer(v[i] + 1);
v// in memoria quindi verrà creato un nuovo oggetto Integer, e il vecchio oggetto diventa inattivo che appena il gc parte lo cancellerà
}
}
}
Inoltre è possibile anche creare delle classi read-only proprie in cui tutti i dati sono private e nessuno dei metodi public modifica tali dati.
La creazione di una classe immutabile può causare frequenti attivazioni del gc, oltre ad avere un costo aggiuntivo dovuto alla creazione di nuovi oggetti.
La soluzione consiste nel creare una classe simile ma modificabile e saltare da una all’altra a seconda delle esigenze, ovvero creare un compagno di classe che sia mutevole. Per String ad esempio il compagno di classe si chiama StringBuffer (che è pure thread-safe a differenza di String). Il compilatore crea automaticamente un oggetto StringBuffer per valutare certe espressioni, come quelle degli operatori + e += della classe String.