CodeGym /Java Blog /Random-IT /Sequenza di azioni durante la creazione dell'oggetto
John Squirrels
Livello 41
San Francisco

Sequenza di azioni durante la creazione dell'oggetto

Pubblicato nel gruppo Random-IT
CIAO! La lezione di oggi sarà abbastanza... uh... sfaccettata :) nel senso che tratteremo un'ampia gamma di argomenti, ma tutti riguarderanno il processo di creazione degli oggetti . Sequenza di azioni durante la creazione dell'oggetto - 1Lo analizzeremo dall'inizio alla fine: come vengono chiamati i costruttori, come e in quale ordine vengono inizializzati i campi (inclusi i campi statici), ecc. Abbiamo precedentemente toccato alcuni dei punti discussi nell'articolo, quindi puoi dare un'occhiata il materiale sui costruttori di classi base . Innanzitutto, ricordiamo come viene creato un oggetto. Ricordi bene come appare questo processo dal punto di vista di uno sviluppatore: crea una classe, scrive newe 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).
Inoltre, dalla lezione sul ciclo di vita degli oggetti , probabilmente ti ricorderai che un oggetto dura finché c'è almeno un riferimento ad esso. Se non ne rimane nessuno, l'oggetto diventa preda del Garbage Collector. Sequenza di azioni durante la creazione dell'oggetto - 2Questi primi due punti non dovrebbero sollevare particolari questioni. L'allocazione della memoria è un processo semplice e ci sono solo due possibili risultati: o c'è memoria o non c'è :) E la creazione di un collegamento non è insolita. Ma il terzo punto rappresenta tutta una serie di operazioni eseguite in rigoroso ordine. Non sono un fan del cramming per i test, ma devi capire bene questo processo e devi memorizzare questa sequenza di operazioni. Quando abbiamo parlato del processo di creazione degli oggetti nelle lezioni precedenti, non sapevi ancora nulla sull'ereditarietà, quindi spiegare alcune cose era problematico. Ora sai parecchio e possiamo finalmente considerare questa domanda per intero :) Quindi il terzo punto dice " Finalmente, le variabili vengono inizializzate e viene chiamato il costruttore ". Ma in quale ordine avviene tutto questo? Per una migliore comprensione, creiamo due classi super semplici: un genitore e un figlio:

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 Truckclasse è 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:
  1. La prima cosa che accade è che le variabili statiche della Vehicleclasse vengono inizializzate . Sì, ho detto la Vehicleclasse, no Truck. Le variabili statiche vengono inizializzate prima che vengano chiamati i costruttori e questo inizia nella classe genitore. Proviamo a verificarlo. Impostiamo il vehicleCountercampo nella Vehicleclasse uguale a 10 e proviamo a visualizzarlo in entrambi i costruttori Vehiclee Truck.

    
    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 Truckcostruttore per essere sicuri che i campi del camion non siano ancora stati inizializzati quando vehicleCounterviene visualizzato.

    Ed ecco il risultato:

    
    10 
    10
    
  2. Dopo che le variabili statiche della classe genitore sono state inizializzate, vengono inizializzate le variabili statiche della classe figlia. Nel nostro caso, questo è il truckCountercampo della Truckclasse.

    Facciamo un altro esperimento in cui proveremo a visualizzare il valore di truckCounterall'interno del Truckcostruttore 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 Truckinizia il costruttore.

  3. 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 descriptionvariabile in Vehicleclasse 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 Vehiclecostruttore inizia al descriptioncampo è già stato assegnato un valore.

  4. 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 Vehiclecostruttore della classe base, la seconda all'interno del Truckcostruttore. Dobbiamo essere convinti che la linea all'interno Vehiclesia 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.

  5. Ora è il momento di inizializzare i campi non statici della classe figlia, cioè la nostra Truckclasse. 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 alla maxSpeedvariabile e nel Truckcostruttore 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!

  6. Viene chiamato il costruttore della Truckclasse 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 :)

Sequenza di azioni durante la creazione dell'oggetto - 3 Perché è così importante comprendere bene questo processo? Immagina quanto potrebbero essere inaspettati i risultati della creazione di un oggetto ordinario se non sapessi esattamente cosa sta succedendo "sotto il cofano" :) Ora è il momento di tornare al corso e completare alcune attività! Buona fortuna e a presto! :)
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION