new
e tutto è pronto :) Qui parleremo di cosa succede all'interno del computer e della macchina Java quando scriviamo, ad esempio:
Cat cat = new Cat();
Ne abbiamo già parlato prima, ma nel caso ti ricordiamo:
- Innanzitutto, viene allocata la memoria per l'archiviazione dell'oggetto.
- Successivamente, la macchina Java crea un riferimento all'oggetto (nel nostro caso il riferimento è Cat cat).
- Infine, le variabili vengono inizializzate e viene chiamato il costruttore (esamineremo questo processo in modo più dettagliato).
public class Vehicle {
public static int vehicleCounter = 0;
private String description = "Vehicle";
public Vehicle() {
}
public String getDescription() {
return description;
}
}
public class Truck extends Vehicle {
private static int truckCounter = 0;
private int yearOfManufacture;
private String model;
private int maxSpeed;
public Truck(int yearOfManufacture, String model, int maxSpeed) {
this.yearOfManufacture = yearOfManufacture;
this.model = model;
this.maxSpeed = maxSpeed;
Vehicle.vehicleCounter++;
truckCounter++;
}
}
La Truck
classe è un'implementazione di un camion con campi che ne rappresentano l'anno, il modello e la velocità massima. Ora vogliamo creare uno di questi oggetti:
public class Main {
public static void main(String[] args) throws IOException {
Truck truck = new Truck(2017, "Scania S 500 4x2", 220);
}
}
Per la macchina Java, il processo sarà simile a questo:
-
La prima cosa che accade è che le variabili statiche della
Vehicle
classe vengono inizializzate . Sì, ho detto laVehicle
classe, noTruck
. Le variabili statiche vengono inizializzate prima che vengano chiamati i costruttori e questo inizia nella classe genitore. Proviamo a verificarlo. Impostiamo ilvehicleCounter
campo nellaVehicle
classe uguale a 10 e proviamo a visualizzarlo in entrambi i costruttoriVehicle
eTruck
.public class Vehicle { public static int vehicleCounter = 10; private String description = "Vehicle"; public Vehicle() { System.out.println(vehicleCounter); } public String getDescription() { return description; } } public class Truck extends Vehicle { private static int truckCount = 0; private int yearOfManufacture; private String model; private int maxSpeed; public Truck(int yearOfManufacture, String model, int maxSpeed) { System.out.println(vehicleCounter); this.yearOfManufacture = yearOfManufacture; this.model = model; this.maxSpeed = maxSpeed; Vehicle.vehicleCounter++; truckCount++; } }
Abbiamo deliberatamente inserito l'istruzione println all'inizio del
Truck
costruttore per essere sicuri che i campi del camion non siano ancora stati inizializzati quandovehicleCounter
viene visualizzato.Ed ecco il risultato:
10 10
-
Dopo che le variabili statiche della classe genitore sono state inizializzate, vengono inizializzate le variabili statiche della classe figlia. Nel nostro caso, questo è il
truckCounter
campo dellaTruck
classe.Facciamo un altro esperimento in cui proveremo a visualizzare il valore di
truckCounter
all'interno delTruck
costruttore prima che gli altri campi vengano inizializzati:public class Truck extends Vehicle { private static int truckCounter = 10; private int yearOfManufacture; private String model; private int maxSpeed; public Truck(int yearOfManufacture, String model, int maxSpeed) { System.out.println(truckCounter); this.yearOfManufacture = yearOfManufacture; this.model = model; this.maxSpeed = maxSpeed; Vehicle.vehicleCounter++; truckCounter++; } }
Come puoi vedere, il valore 10 è già stato assegnato alla nostra variabile statica quando
Truck
inizia il costruttore. -
Non è ancora il momento per i costruttori! L'inizializzazione della variabile continua. Le variabili non statiche della classe genitore sono inizializzate per terze. Come puoi vedere, l'ereditarietà complica notevolmente il processo di creazione di un oggetto, ma non c'è niente che tu possa fare al riguardo: devi solo memorizzare alcune cose nella programmazione :)
Come esperimento, possiamo assegnare un valore iniziale alla
description
variabile inVehicle
classe e poi cambiarlo nel costruttore.public class Vehicle { public static int vehicleCounter = 10; private String description = "Initial value of the description field"; public Vehicle() { System.out.println(description); description = "Vehicle"; System.out.println(description); } public String getDescription() { return description; } }
Eseguiamo il nostro
main()
metodo che crea un camion:public class Main { public static void main(String[] args) throws IOException { Truck truck = new Truck(2017, "Scania S 500 4x2", 220); } }
Otteniamo il seguente risultato:
Initial value of the description field Vehicle
Ciò dimostra che quando il
Vehicle
costruttore inizia aldescription
campo è già stato assegnato un valore. -
Finalmente è il momento dei costruttori! Più precisamente, è il momento del costruttore della classe base. Viene richiamato nella quarta fase del processo di creazione dell'oggetto.
Anche questo è abbastanza facile da verificare. Proviamo a inviare due righe alla console: una all'interno del
Vehicle
costruttore della classe base, la seconda all'interno delTruck
costruttore. Dobbiamo essere convinti che la linea all'internoVehicle
sia visualizzata per prima:public Vehicle() { System.out.println("Hello from the Vehicle constructor!"); } public Truck(int yearOfManufacture, String model, int maxSpeed) { System.out.println("Hello from the Truck constructor!"); this.yearOfManufacture = yearOfManufacture; this.model = model; this.maxSpeed = maxSpeed; Vehicle.vehicleCounter++; truckCounter++; }
Eseguiremo il nostro
main()
metodo e osserveremo il risultato:Hello from the Vehicle constructor! Hello from the Truck constructor!
Eccellente. Ciò significa che non ci stiamo sbagliando :) Andiamo avanti.
-
Ora è il momento di inizializzare i campi non statici della classe figlia, cioè la nostra
Truck
classe. I campi immediatamente all'interno della classe che viene istanziata non vengono inizializzati fino al quinto passaggio! Sorprendente, ma vero :) Ancora una volta, faremo un semplice controllo, proprio come con la classe genitore: daremo un valore iniziale allamaxSpeed
variabile e nelTruck
costruttore verificheremo che il valore sia stato assegnato prima dell'inizio del costruttore:public class Truck extends Vehicle { private static int truckCounter = 10; private int yearOfManufacture; private String model; private int maxSpeed = 150; public Truck(int yearOfManufacture, String model, int maxSpeed) { System.out.println("Initial value of maxSpeed = " + this.maxSpeed); this.yearOfManufacture = yearOfManufacture; this.model = model; this.maxSpeed = maxSpeed; Vehicle.vehicleCounter++; truckCounter++; } }
Uscita console:
Initial value of maxSpeed = 150
Come puoi vedere, quando il
Truck
costruttore si avvia,maxSpeed
è già uguale a 150! -
Viene chiamato il costruttore della
Truck
classe figlia.E solo a questo punto, per ultimo, verrà chiamato il costruttore della classe che stiamo istanziando!
Solo nel sesto passaggio verranno assegnati ai campi i valori che passiamo come argomenti al nostro camion.
Come puoi vedere, "costruire" un camion, cioè il processo di creazione dell'oggetto, non è semplice. Ma sembra che l'abbiamo scomposto nelle parti più piccole :)
GO TO FULL VERSION