
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).

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:
The first thing that happens is the static variables of the
Vehicle
class are initialized. Yes, I said theVehicle
class, notTruck
. Static variables are initialized before constructors are called, and this starts in the parent class. Let's try to verify this. We set thevehicleCounter
field in theVehicle
class equal to 10 and try to display it in both theVehicle
andTruck
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 whenvehicleCounter
is displayed.And here's the result:
10 10
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 theTruck
class.Let's do another experiment where we'll try to display the value of
truckCounter
inside theTruck
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.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 inVehicle
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 thedescription
field has already been assigned a value.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 theTruck
constructor. We need to be convinced that the line insideVehicle
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.
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 themaxSpeed
variable and in theTruck
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!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 :)

GO TO FULL VERSION