
new
e está tudo pronto :) Aqui falaremos sobre o que acontece dentro do computador e da máquina Java quando escrevemos, por exemplo:
Cat cat = new Cat();
Já falamos sobre isso antes, mas só para garantir, vamos lembrá-lo:
- Primeiro, a memória para armazenar o objeto é alocada.
- Em seguida, a máquina Java cria uma referência ao objeto (no nosso caso, a referência é Cat cat).
- Por fim, as variáveis são inicializadas e o construtor é chamado (vamos ver esse processo com mais detalhes).

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++;
}
}
A Truck
classe é uma implementação de um caminhão com campos representando seu ano, modelo e velocidade máxima. Agora queremos criar um desses objetos:
public class Main {
public static void main(String[] args) throws IOException {
Truck truck = new Truck(2017, "Scania S 500 4x2", 220);
}
}
Para a máquina Java, o processo ficará assim:
-
A primeira coisa que acontece é que as variáveis estáticas da
Vehicle
classe são inicializadas . Sim, eu disse aVehicle
classe, nãoTruck
. As variáveis estáticas são inicializadas antes que os construtores sejam chamados, e isso começa na classe pai. Vamos tentar verificar isso. Definimos ovehicleCounter
campo naVehicle
classe igual a 10 e tentamos exibi-lo nos construtoresVehicle
eTruck
.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++; } }
Colocamos deliberadamente a instrução println bem no início do
Truck
construtor para garantir que os campos do caminhão ainda não tenham sido inicializados quandovehicleCounter
for exibido.E aqui está o resultado:
10 10
-
Depois que as variáveis estáticas da classe pai são inicializadas, as variáveis estáticas da classe filha são inicializadas. No nosso caso, este é o
truckCounter
campo daTruck
classe.Vamos fazer outro experimento onde tentaremos exibir o valor de
truckCounter
dentro doTruck
construtor antes que os outros campos sejam inicializados: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++; } }
Como você pode ver, o valor 10 já foi atribuído à nossa variável estática quando o
Truck
construtor começou. -
Ainda não é a hora dos construtores! A inicialização da variável continua. As variáveis não estáticas da classe pai são inicializadas em terceiro lugar. Como você pode ver, a herança complica significativamente o processo de criação de um objeto, mas não há nada que você possa fazer a respeito: você só precisa memorizar algumas coisas na programação :)
Como experiência, podemos atribuir algum valor inicial à
description
variável naVehicle
classe e depois alterá-lo no construtor.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; } }
Vamos executar nosso
main()
método que cria um caminhão:public class Main { public static void main(String[] args) throws IOException { Truck truck = new Truck(2017, "Scania S 500 4x2", 220); } }
Obtemos o seguinte resultado:
Initial value of the description field Vehicle
Isso prova que, quando o
Vehicle
construtor começa, odescription
campo já recebeu um valor. -
Finalmente, é a vez dos construtores! Mais precisamente, é hora do construtor da classe base. Ele é invocado na quarta etapa do processo de criação do objeto.
Isso também é bastante fácil de verificar. Vamos tentar enviar duas linhas para o console: uma dentro do
Vehicle
construtor da classe base, a segunda dentro doTruck
construtor. Precisamos estar convencidos de que a linha internaVehicle
é exibida primeiro: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++; }
Vamos executar nosso
main()
método e ver o resultado:Hello from the Vehicle constructor! Hello from the Truck constructor!
Excelente. Isso significa que não estamos enganados :) Vamos em frente.
-
Agora é hora de inicializar os campos não estáticos da classe filha, ou seja, nossa
Truck
classe. Os campos imediatamente dentro da classe que está sendo instanciada não são inicializados até a quinta etapa! Surpreendente, mas é verdade :) Mais uma vez, faremos uma verificação simples — assim como na classe pai: atribuiremos algum valor inicial àmaxSpeed
variável e noTruck
construtor verificaremos se o valor foi atribuído antes do início do construtor: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++; } }
Saída do console:
Initial value of maxSpeed = 150
Como você pode ver, quando o
Truck
construtor inicia,maxSpeed
já é igual a 150! -
O construtor da
Truck
classe filha é chamado.E somente neste ponto, por último, será chamado o construtor da classe que estamos instanciando!
Somente na sexta etapa serão atribuídos aos campos os valores que passamos como argumentos para nosso caminhão.
Como você pode ver, "construir" um caminhão, ou seja, o processo de criação do objeto, não é simples. Mas parece que dividimos em partes menores :)

GO TO FULL VERSION