JavaRush /Java Blog /Random EN /Procedure for creating an object

Procedure for creating an object

Published in the Random EN group
Hello! Today's lecture will be quite...uh...versatile :) In the sense that we will cover a wide range of topics, but they will all be related to the process of creating an object . We will analyze it from beginning to end: how constructors are called, how and in what order fields are initialized (including static ones), etc. We touched on some of the points discussed in the article earlier, so you can skim through the material about the base class constructor . First, let's remember how an object is created. Well, how this process looks like from a developer's point of view, you remember well: you created a class, wrote it new- and you're done :) Here we'll talk about what happens inside a computer and a Java machine when we write, for example:
Cat cat = new Cat();
We've talked about this before, but just in case, remember:
  1. First, memory is allocated to store the object.
  2. Next, the Java machine creates a link to this object (in our case, the link is Cat cat).
  3. At the end, the variables are initialized and the constructor is called (we will consider this process in more detail).
In addition, from the lecture on the life cycle of an object, you probably remember that it lasts as long as there is at least one reference to it. If there are none left, the object will become a prey for the garbage collector. Procedure for creating an object - 2The first two points of special questions should not cause. Memory allocation is a simple process, and the result can be only one of two: either there is memory or it is not :) Creating a link is also nothing unusual. But point number three is a whole set of operations going in a strictly defined order. I'm not a fan of cramming as a means to learn something, but you should understand this process well, and you need to know this order by heart. When we talked about the process of creating objects in previous lectures, you still didn’t really know anything about inheritance, so it was problematic to explain some points. Now the volume of your knowledge is quite large, and we can finally consider this issue fully :) So, the third paragraph says that “ at the end, the variables are initialized and the constructor is called. “But in what order is it all done? For a better understanding, let's create two simple classes - parent and child:
public class Car {

   public static int carCounter = 0;

   private String description = "Абстрактная машина";

   public Car() {
   }

   public String getDescription() {
       return description;
   }
}

public class Truck extends Car {

   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;

       Car.carCounter++;
       truckCounter++;
   }
}
The class Truckis an implementation of a truck: with fields reflecting its year of manufacture, model, and maximum speed. So we want to create one such object:
public class Main {

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

       Truck truck = new Truck(2017, "Scania S 500 4x2", 220);
   }
}
Here is how this process will look from the point of view of the Java machine:
  1. The first thing that happens is that the static class variables are initializedCar . Yes, yes, exactly the class Car, not the Truck . Static variables are initialized before constructors are called, and this begins in the parent class. Let's try to check. Let's set the counter carCounterin the class Carto 10 and try to output it to the console in both constructors - Carand Truck.

    public class Car {
    
       public static int carCounter = 10;
    
       private String description = "Абстрактная машина";
    
       public Car() {
           System.out.println(carCounter);
       }
    
       public String getDescription() {
           return description;
       }
    }
    
    public class Truck extends Car {
    
       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(carCounter);
           this.yearOfManufacture = yearOfManufacture;
           this.model = model;
           this.maxSpeed = maxSpeed;
    
           Car.carCounter++;
           truckCount++;
       }
    }

    We deliberately put the output to the console at the very beginning of the constructor Truckin order to know for sure: the truck fields carCounterhad not yet been initialized at the time 'a was output to the console.

    And here is the result:

    
    10
    10
  2. After the static variables of the ancestor class are initialized, the static variables of the child class are initialized. That is, in our case, a truckCounterclass field Truck.

    Again, let's experiment and try to output the value of truckCounter'a inside the constructor Truckbefore the rest of the fields are initialized:

    public class Truck extends Car {
    
       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;
    
           Car.carCounter++;
           truckCounter++;
       }
    }

    As you can see, the value 10 was already assigned to our static variable when the constructor Truckstarted its work.

  3. The time of designers has not come yet! Variable initialization continues. The third in a row will be initialized non-static variables of the ancestor class. As you can see, inheritance significantly complicates the process of creating an object, but there's nothing you can do about it: some things in programming you just have to remember :)

    For the experiment, we can assign some initial value to descriptiona class variable, and then change it in the constructor.Car

    public class Car {
    
       public static int carCounter = 10;
    
       private String description = "Начальное meaning поля description";
    
       public Car() {
           System.out.println(description);
           description = "Абстрактная машина";
           System.out.println(description);
       }
    
       public String getDescription() {
           return description;
       }
    }

    Let's run our method main()with the creation of a truck:

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

    And we get the result:

    
    Начальное meaning поля description
    Абстрактная машина

    CarThis proves that the field descriptionalready had a value assigned when the constructor started .

  4. Finally, it came to the designers! More precisely, to the base class constructor. The beginning of its work is the fourth point in the process of creating an object.

    It's easy enough to check this too. Let's try to output two lines to the console: one inside the base constructor Car, and the second inside the constructor Truck. We need to make sure the line inside Caris printed first:

    public Car() {
       System.out.println("Привет из конструктора Car!");
    }
    
    public Truck(int yearOfManufacture, String model, int maxSpeed) {
    
       System.out.println("Привет из конструктора Truck!");
       this.yearOfManufacture = yearOfManufacture;
       this.model = model;
       this.maxSpeed = maxSpeed;
    
       Car.carCounter++;
       truckCounter++;
    }

    We run our method main()and look at the result:

    
    Привет из конструктора Car!
    Привет из конструктора Truck!

    Great, so we weren't mistaken :) Let's move on.

  5. Now it's the turn to initialize the non-static fields of the child class , that is, our class Truck. The fields of the class whose object we are creating are only initialized in the fifth order! Surprising, but true :) Again, let's do a simple check, the same as with the parent class: assign some initial value to the variable and check in the constructor that it was assigned before the constructor started work:maxSpeedTruck

    public class Truck extends Car {
    
       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("Изначальное meaning maxSpeed = " + this.maxSpeed);
           this.yearOfManufacture = yearOfManufacture;
           this.model = model;
           this.maxSpeed = maxSpeed;
    
           Car.carCounter++;
           truckCounter++;
       }
    }

    Console output:

    
    Изначальное meaning maxSpeed = 150

    As you can see, at the moment the constructor started, Truckthe value maxSpeedwas already equal to 150!

  6. The constructor of the child class is called Truck.

    And only now, lastly, the constructor of the class whose object we are creating will be called!

    Only at the sixth stage, the fields will be assigned the values ​​that we will pass as parameters to our truck.

    As you can see, the "design" of the truck, i.e. the process of creating an object is not an easy thing. But we seem to have dismantled it to the smallest detail :)

Procedure for creating an object - 3Why is it so important to understand this process well? Imagine how unexpected the results of creating a normal object can be if you don't know exactly what's going on "under the hood" :) It's time to get back on course and solve a few problems! Good luck and see you again :)Procedure for creating an object - 4
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION