
new
i wszystko gotowe :) Tutaj porozmawiamy o tym, co dzieje się wewnątrz komputera i maszyny Java, kiedy piszemy, na przykład:
Cat cat = new Cat();
Już o tym rozmawialiśmy, ale na wszelki wypadek przypomnimy:
- Najpierw przydzielana jest pamięć do przechowywania obiektu.
- Następnie maszyna Java tworzy referencję do obiektu (w naszym przypadku referencją jest Cat cat).
- Na koniec inicjowane są zmienne i wywoływany jest konstruktor (przyjrzymy się temu procesowi bardziej szczegółowo).

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++;
}
}
Klasa Truck
jest implementacją ciężarówki z polami reprezentującymi jej rok, model i maksymalną prędkość. Teraz chcemy stworzyć jeden taki obiekt:
public class Main {
public static void main(String[] args) throws IOException {
Truck truck = new Truck(2017, "Scania S 500 4x2", 220);
}
}
Dla maszyny Java proces będzie wyglądał następująco:
-
Pierwszą rzeczą, która się dzieje, jest zainicjowanie zmiennych statycznych klasy
Vehicle
. Tak, powiedziałem, żeVehicle
klasa, a nieTruck
. Zmienne statyczne są inicjowane przed wywołaniem konstruktorów i zaczyna się to w klasie nadrzędnej. Spróbujmy to zweryfikować. UstawiamyvehicleCounter
pole wVehicle
klasie na 10 i staramy się je wyświetlić zarówno w konstruktorzeVehicle
jak iwTruck
konstruktorze.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++; } }
Celowo umieściliśmy instrukcję println na samym początku konstruktora,
Truck
aby upewnić się, że pola ciężarówki nie zostały jeszcze zainicjowane, gdyvehicleCounter
wyświetla się .A oto wynik:
10 10
-
Po zainicjowaniu zmiennych statycznych klasy nadrzędnej, inicjowane są zmienne statyczne klasy potomnej. W naszym przypadku jest to
truckCounter
pole klasyTruck
.Zróbmy kolejny eksperyment, w którym spróbujemy wyświetlić wartość
truckCounter
wewnątrzTruck
konstruktora przed zainicjowaniem innych pól: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++; } }
Jak widać, wartość 10 została już przypisana do naszej zmiennej statycznej w momencie
Truck
startu konstruktora. -
To jeszcze nie czas na konstruktorów! Inicjalizacja zmiennej jest kontynuowana. Zmienne niestatyczne klasy nadrzędnej są inicjowane jako trzecie. Jak widać, dziedziczenie znacznie komplikuje proces tworzenia obiektu, ale nic na to nie poradzisz: Trzeba tylko zapamiętać pewne rzeczy w programowaniu :)
W ramach eksperymentu możemy przypisać zmiennej
description
wVehicle
klasie pewną wartość początkową, a następnie zmienić ją w konstruktorze.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; } }
Uruchommy naszą
main()
metodę, która tworzy ciężarówkę:public class Main { public static void main(String[] args) throws IOException { Truck truck = new Truck(2017, "Scania S 500 4x2", 220); } }
Otrzymujemy następujący wynik:
Initial value of the description field Vehicle
Dowodzi to, że gdy
Vehicle
konstruktor zaczyna,description
pole ma już przypisaną wartość. -
W końcu przyszedł czas na konstruktorów! Mówiąc dokładniej, nadszedł czas na konstruktor klasy bazowej. Jest ona wywoływana w czwartym kroku procesu tworzenia obiektu.
To też jest dość łatwe do zweryfikowania. Spróbujmy wypisać dwie linie do konsoli: jedną wewnątrz
Vehicle
konstruktora klasy bazowej, drugą wewnątrzTruck
konstruktora. Musimy być przekonani, że linia wewnątrzVehicle
jest wyświetlana jako pierwsza: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++; }
Uruchomimy naszą
main()
metodę i spojrzymy na wynik:Hello from the Vehicle constructor! Hello from the Truck constructor!
Doskonały. To znaczy, że się nie mylimy :) Przejdźmy dalej.
-
Teraz czas na inicjalizację pól niestatycznych klasy potomnej, czyli naszej
Truck
. Pola bezpośrednio w tworzonej klasie nie są inicjowane aż do piątego kroku! Zaskakujące, ale prawdziwe :) Ponownie zrobimy proste sprawdzenie — podobnie jak w przypadku klasy nadrzędnej: podamy wartość początkową zmiennej,maxSpeed
awTruck
konstruktorze sprawdzimy, czy wartość została przypisana przed uruchomieniem konstruktora: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++; } }
Wyjście konsoli:
Initial value of maxSpeed = 150
Jak widać, gdy
Truck
konstruktor startuje,maxSpeed
jest już równe 150! -
Konstruktor
Truck
klasy potomnej jest wywoływany.I dopiero w tym momencie zostanie wywołany konstruktor klasy, którą tworzymy!
Dopiero w szóstym kroku do pól zostaną przypisane wartości, które przekazujemy jako argumenty do naszej ciężarówki.
Jak widać „konstruowanie” ciężarówki, czyli proces tworzenia obiektu, nie jest proste. Ale wygląda na to, że podzieliliśmy to na najmniejsze części :)

GO TO FULL VERSION