CodeGym/Blog Java/Random-FR/Séquence d'actions lors de la création d'un objet
Auteur
Pavlo Plynko
Java Developer at CodeGym

Séquence d'actions lors de la création d'un objet

Publié dans le groupe Random-FR
membres
Salut! La leçon d'aujourd'hui sera assez... euh... multiforme :) dans le sens où nous couvrirons un large éventail de sujets, mais ils seront tous liés au processus de création d'objet . Séquence d'actions lors de la création d'un objet - 1Nous allons l'analyser du début à la fin : comment les constructeurs sont appelés, comment et dans quel ordre les champs (y compris les champs statiques) sont initialisés, etc. Nous avons déjà abordé certains des points abordés dans l'article, vous pouvez donc survoler le matériel sur les constructeurs de classe de base . Rappelons tout d'abord comment un objet est créé. Vous vous souvenez bien à quoi ressemble ce processus du point de vue d'un développeur : il crée une classe, écrit newet tout est prêt :) Ici, nous allons parler de ce qui se passe à l'intérieur de l'ordinateur et de la machine Java lorsque nous écrivons, par exemple :
Cat cat = new Cat();
Nous en avons déjà parlé, mais au cas où nous vous rappellerions :
  • Tout d'abord, la mémoire pour stocker l'objet est allouée.
  • Ensuite, la machine Java crée une référence à l'objet (dans notre cas, la référence est Cat cat).
  • Enfin, les variables sont initialisées et le constructeur est appelé (nous allons voir ce processus plus en détail).
De plus, de la leçon sur le cycle de vie d'un objet , vous vous rappelez probablement qu'un objet dure tant qu'il y a au moins une référence à celui-ci. S'il n'en reste plus, l'objet devient la proie du ramasse-miettes. Séquence d'actions lors de la création d'un objet - 2Ces deux premiers points ne doivent pas soulever de questions particulières. L'allocation de mémoire est un processus simple, et il n'y a que deux résultats possibles : soit il y a de la mémoire, soit il n'y en a pas :) Et créer un lien n'est pas inhabituel. Mais le troisième point représente tout un ensemble d'opérations exécutées dans un ordre strict. Je ne suis pas fan du bachotage pour les tests, mais vous devez bien comprendre ce processus et vous devez mémoriser cette séquence d'opérations. Lorsque nous avons parlé du processus de création d'objets dans les leçons précédentes, vous ne connaissiez pas encore vraiment l'héritage, donc expliquer certaines choses était problématique. Maintenant, vous en savez pas mal et nous pouvons enfin considérer cette question dans son intégralité :) Donc le troisième point dit " Enfin, les variables sont initialisées et le constructeur est appelé. " Mais dans quel ordre tout cela se passe-t-il ? Pour une meilleure compréhension, créons deux classes super simples — un parent et un enfant :
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 est une implémentation d'un camion avec des champs représentant son année, son modèle et sa vitesse maximale. Maintenant, nous voulons créer un tel objet :
public class Main {

   public static void main(String[] args) throws IOException {

       Truck truck = new Truck(2017, "Scania S 500 4x2", 220);
   }
}
Pour la machine Java, le processus ressemblera à ceci :
  1. La première chose qui se passe est que les variables statiques de la Vehicleclasse sont initialisées . Oui, j'ai bien dit la Vehicleclasse, non Truck. Les variables statiques sont initialisées avant l'appel des constructeurs, et cela commence dans la classe parent. Essayons de vérifier cela. Nous définissons le vehicleCounterchamp de la Vehicleclasse égal à 10 et essayons de l'afficher à la fois dans les constructeurs Vehicleet 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++;
       }
    }

    Nous avons délibérément placé l'instruction println au tout début du Truckconstructeur pour être sûr que les champs du camion n'ont pas encore été initialisés lorsque vehicleCounters'affiche.

    Et voici le résultat :

    10
    10
  2. Une fois les variables statiques de la classe parent initialisées, les variables statiques de la classe enfant sont initialisées. Dans notre cas, il s'agit du truckCounterchamp de la Truckclasse.

    Faisons une autre expérience où nous essaierons d'afficher la valeur de à truckCounterl'intérieur du Truckconstructeur avant que les autres champs ne soient initialisés :

    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++;
       }
    }

    Comme vous pouvez le voir, la valeur 10 a déjà été affectée à notre variable statique au Truckdémarrage du constructeur.

  3. Ce n'est toujours pas l'heure des constructeurs ! L'initialisation des variables continue. Les variables non statiques de la classe parent sont initialisées en troisième. Comme vous pouvez le voir, l'héritage complique considérablement le processus de création d'un objet, mais vous n'y pouvez rien : il suffit de mémoriser certaines choses en programmation :)

    À titre expérimental, nous pouvons attribuer une valeur initiale à la descriptionvariable dans Vehiclela classe, puis la modifier dans le constructeur.

    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;
       }
    }

    Exécutons notre main()méthode qui crée un camion :

    public class Main {
    
       public static void main(String[] args) throws IOException {
    
           Truck truck = new Truck(2017, "Scania S 500 4x2", 220);
       }
    }

    Nous obtenons le résultat suivant :

    Initial value of the description field
    Vehicle

    Cela prouve que lorsque le Vehicleconstructeur commence, le descriptionchamp a déjà reçu une valeur.

  4. Enfin, place aux constructeurs ! Plus précisément, il est temps pour le constructeur de la classe de base. Il est appelé à la quatrième étape du processus de création d'objet.

    C'est aussi assez facile à vérifier. Essayons de sortir deux lignes vers la console : une à l'intérieur du Vehicleconstructeur de la classe de base, la seconde à l'intérieur du Truckconstructeur. Nous devons être convaincus que la ligne à l'intérieur Vehicleest affichée en premier :

    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++;
    }

    Nous allons exécuter notre main()méthode et regarder le résultat :

    Hello from the Vehicle constructor!
    Hello from the Truck constructor!

    Excellent. Cela signifie que nous ne nous trompons pas :) Passons à autre chose.

  5. Il est maintenant temps d' initialiser les champs non statiques de la classe enfant, c'est-à-dire notre Truckclasse. Les champs immédiatement à l'intérieur de la classe en cours d'instanciation ne sont initialisés qu'à la cinquième étape ! Surprenant, mais vrai :) Encore une fois, nous allons faire une simple vérification — comme avec la classe parent : nous donnerons une valeur initiale à la maxSpeedvariable et dans le Truckconstructeur, nous vérifierons que la valeur a été assignée avant le démarrage du constructeur :

    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++;
       }
    }

    Sortie console :

    Initial value of maxSpeed = 150

    Comme vous pouvez le voir,  au démarrage du Truck constructeur, maxSpeed est déjà égal à 150 !

  6. Le constructeur de la Truckclasse enfant est appelé.

    Et ce n'est qu'à ce stade, en dernier lieu, que le constructeur de la classe que nous instancions sera appelé !

    Ce n'est qu'à la sixième étape que les champs se verront attribuer les valeurs que nous transmettons en tant qu'arguments à notre camion.

    Comme vous pouvez le voir, "construire" un camion, c'est-à-dire le processus de création d'objets, n'est pas simple. Mais il semble que nous l'ayons décomposé en plus petites parties :)

Séquence d'actions lors de la création d'un objet - 3 Pourquoi est-il si important de bien comprendre ce processus ? Imaginez à quel point les résultats de la création d'un objet ordinaire pourraient être inattendus si vous ne saviez pas exactement ce qui se passait "sous le capot" :) Il est maintenant temps de reprendre le cours et d'effectuer certaines tâches ! Bonne chance et à bientôt ! :)
Commentaires
  • Populaires
  • Nouveau
  • Anciennes
Tu dois être connecté(e) pour laisser un commentaire
Cette page ne comporte pas encore de commentaires