Hi! Today's lesson will be quite... uh... multifaceted :) in the sense that we will cover a wide range of topics, but they will all relate to the object creation process. Sequence of actions during object creation - 1We will analyze it from beginning to end: how constructors are called, how and in what order fields (including static fields) are initialized, etc. We've previously touched on some of the points discussed in the article, so you can glance over the material on base class constructors. First, let's recall how an object is created. You well remember how this process looks from a developer's point of view: he creates a class, writes new, and everything is ready :) Here we'll talk about what happens inside the computer and the Java machine when we write, for example:

Cat cat = new Cat();
We've talked about this before, but just in case we'll remind you:
  • First, memory for storing the object is allocated.
  • Next, the Java machine creates a reference to the object (in our case the reference is Cat cat).
  • Finally, variables are initialized and the constructor is called (we're going to look at this process in more detail).
In addition, from the lesson on the object life cycle, you probably remember that an object lasts as long as there is at least one reference to it. If there are none left, then the object becomes prey for the garbage collector. Sequence of actions during object creation - 2These first two points should not raise any special questions. Memory allocation is a simple process, and there are only two possible outcomes: either there is memory or there is not :) And creating a link is not unusual. But the third point represents a whole set of operations executed in strict order. I'm not a fan of cramming for tests, but you need to understand this process well and you need to memorize this sequence of operations. When we talked about the object creation process in previous lessons, you didn't really know anything about inheritance yet, so explaining some things was problematic. Now you know quite a lot and we can finally consider this question in full :) So the third point says "Finally, variables are initialized and the constructor is called." But what order does all this happen in? For a better understanding, let's create two super simple classes — a parent and a child:

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++; 
   } 
}
The Truck class is an implementation of a truck with fields representing its year, model, and maximum speed. Now 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); 
   } 
}
To the Java machine, the process will look like this:
  1. The first thing that happens is the static variables of the Vehicle class are initialized. Yes, I said the Vehicle class, not Truck. Static variables are initialized before constructors are called, and this starts in the parent class. Let's try to verify this. We set the vehicleCounter field in the Vehicle class equal to 10 and try to display it in both the Vehicle and Truck constructors.

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

    We deliberately put the println statement at the very beginning of the Truck constructor to be sure that the truck's fields haven't yet been initialized when vehicleCounter is displayed.

    And here's the result:

    
    10 
    10
    
  2. After the static variables of the parent class are initialized, the static variables of the child class are initialized. In our case, this is the truckCounter field of the Truck class.

    Let's do another experiment where we'll try to display the value of truckCounter inside the Truck constructor before the other fields are initialized:

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

    As you can see, the value 10 has already been assigned to our static variable when the Truck constructor begins.

  3. It's still not time for the constructors! Variable initialization continues. The non-static variables of the parent class are initialized third.  As you can see, inheritance significantly complicates the process of creating an object, but there's nothing you can do about it: You just have to memorize some things in programming :)

    As an experiment, we can assign some initial value to the description variable in Vehicle class, and then change it in the constructor.

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

    Let's run our main() method that creates a truck:

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

    We get the following result:

    
    Initial value of the description field 
    Vehicle
    

    This proves that when the Vehicle constructor begins the description field has already been assigned a value.

  4. Finally, it is time for the constructors! More precisely, it is time for the base class constructor. It is invoked in the fourth step of the object creation process.

    This is also fairly easy to verify. Let's try outputting two lines to the console: one inside the Vehicle base class constructor, the second inside the Truck constructor. We need to be convinced that the line inside Vehicle is displayed first:

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

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

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

    Excellent. That means we're not mistaken :) Let's move on.

  5. Now it's time for initialization of the non-static fields of the child class, i.e. our Truck class. The fields immediately within the class being instantiated are not initialized until the fifth step! Surprising, but true :) Again, we'll do a simple check — just like with the parent class: we'll some initial value to the maxSpeed variable and in the Truck constructor we'll check that the value was assigned before the constructor started:

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

    Console output:

    
    Initial value of maxSpeed = 150
    

    As you can see,  when the Truck constructor starts, maxSpeed is already equal to 150!

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

    And only at this point, last of all, will the constructor of the class we are instantiating be called!

    Only in the sixth step will the fields be assigned the values that we pass as arguments to our truck.

    As you can see, "constructing" a truck, i.e. the object creation process, is not simple. But it seems that we've broken it down into the smallest parts :)

Sequence of actions during object creation - 3 Why is it so important to understand this process well? Imagine how unexpected the results of creating an ordinary object could be if you didn't know exactly what was happening "under the hood" :) Now it's time to return to the course and complete some tasks! Good luck and see you soon! :)