CodeGym/Blog Java/Random-PL/Kolejność czynności podczas tworzenia obiektu
Autor
Pavlo Plynko
Java Developer at CodeGym

Kolejność czynności podczas tworzenia obiektu

Opublikowano w grupie Random-PL
Cześć! Dzisiejsza lekcja będzie dość... hm... wieloaspektowa :) w tym sensie, że poruszymy szeroki zakres tematów, ale wszystkie będą dotyczyły procesu tworzenia obiektów . Kolejność czynności podczas tworzenia obiektu - 1Przeanalizujemy to od początku do końca: jak wywoływane są konstruktory, jak iw jakiej kolejności inicjowane są pola (w tym pola statyczne) itp. Wcześniej poruszyliśmy niektóre kwestie omówione w artykule, więc możesz rzucić okiem materiał na temat konstruktorów klas bazowych . Najpierw przypomnijmy sobie, jak powstaje obiekt. Dobrze pamiętasz, jak ten proces wygląda z punktu widzenia programisty: tworzy klasę, pisze newi 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).
Ponadto z lekcji o cyklu życia obiektu zapewne pamiętasz, że przedmiot istnieje tak długo, jak długo istnieje co najmniej jedno odniesienie do niego. Jeśli ich nie ma, obiekt staje się ofiarą śmieciarza. Kolejność czynności podczas tworzenia obiektu - 2Te dwa pierwsze punkty nie powinny rodzić żadnych specjalnych pytań. Alokacja pamięci to prosty proces, a możliwe są tylko dwa wyniki: albo jest pamięć, albo jej nie ma :) A tworzenie linku nie jest niczym niezwykłym. Ale trzeci punkt reprezentuje cały zestaw operacji wykonywanych w ściśle określonej kolejności. Nie jestem fanem wkuwania do testów, ale trzeba dobrze zrozumieć ten proces i zapamiętać tę sekwencję działań. Kiedy rozmawialiśmy o procesie tworzenia obiektów na poprzednich lekcjach, tak naprawdę nie wiedziałeś jeszcze nic o dziedziczeniu, więc wyjaśnienie niektórych rzeczy było problematyczne. Teraz już wiesz całkiem sporo i możemy w końcu zająć się tym pytaniem w całości :) A więc trzeci punkt mówi " Na koniec inicjowane są zmienne i wywoływany jest konstruktor ". Ale w jakiej kolejności to wszystko się dzieje? Dla lepszego zrozumienia utwórzmy dwie bardzo proste klasy — rodzica i dziecko:
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 Truckjest 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:
  1. Pierwszą rzeczą, która się dzieje, jest zainicjowanie zmiennych statycznych klasyVehicle . Tak, powiedziałem, że Vehicleklasa, a nie Truck. Zmienne statyczne są inicjowane przed wywołaniem konstruktorów i zaczyna się to w klasie nadrzędnej. Spróbujmy to zweryfikować. Ustawiamy vehicleCounterpole w Vehicleklasie na 10 i staramy się je wyświetlić zarówno w konstruktorze Vehiclejak iw Truckkonstruktorze.

    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, Truckaby upewnić się, że pola ciężarówki nie zostały jeszcze zainicjowane, gdy vehicleCounterwyświetla się .

    A oto wynik:

    10
    10
  2. Po zainicjowaniu zmiennych statycznych klasy nadrzędnej, inicjowane są zmienne statyczne klasy potomnej. W naszym przypadku jest to truckCounterpole klasy Truck.

    Zróbmy kolejny eksperyment, w którym spróbujemy wyświetlić wartość truckCounterwewnątrz Truckkonstruktora 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 Truckstartu konstruktora.

  3. 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 descriptionw Vehicleklasie 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 Vehiclekonstruktor zaczyna, descriptionpole ma już przypisaną wartość.

  4. 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 Vehiclekonstruktora klasy bazowej, drugą wewnątrz Truckkonstruktora. Musimy być przekonani, że linia wewnątrz Vehiclejest 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.

  5. 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, maxSpeedaw Truckkonstruktorze 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!

  6. Konstruktor Truckklasy 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 :)

Kolejność czynności podczas tworzenia obiektu - 3 Dlaczego tak ważne jest dobre zrozumienie tego procesu? Wyobraź sobie, jak nieoczekiwane mogłyby być efekty tworzenia zwykłego przedmiotu, gdybyś nie wiedział dokładnie, co dzieje się „pod maską” :) Teraz czas wrócić do kursu i wykonać kilka zadań! Powodzenia i do zobaczenia wkrótce! :)
Komentarze
  • Popularne
  • Najnowsze
  • Najstarsze
Musisz się zalogować, aby dodać komentarz
Ta strona nie ma jeszcze żadnych komentarzy