CodeGym /Java блог /Случаен /Последователност от действия при създаване на обект
John Squirrels
Ниво
San Francisco

Последователност от действия при създаване на обект

Публикувано в групата
здрасти Днешният урок ще бъде доста... ъъъ... многостранен :) в смисъл, че ще покрием широк кръг от теми, но всички те ще се отнасят до процеса на създаване на обекти . Последователност от действия при създаване на обект - 1Ще го анализираме от началото до края: How се извикват конструкторите, How и в Howъв ред се инициализират полета (включително статичните полета) и т.н. По-рано засегнахме някои от точките, обсъдени в статията, така че можете да погледнете материалът за конструкторите на базов клас . Първо, нека си припомним How се създава обект. Добре си спомняте How изглежда този процес от гледна точка на разработчика: той създава клас, пише newи всичко е готово :) Тук ще говорим Howво се случва вътре в компютъра и Java машината, когато пишем, например:

Cat cat = new Cat();
Говорor сме за това и преди, но за всеки случай ще ви напомним:
  • Първо се разпределя памет за съхраняване на обекта.
  • След това Java машината създава препратка към обекта (в нашия случай препратката е Cat cat).
  • Накрая се инициализират променливите и се извиква конструкторът (ще разгледаме този процес по-подробно).
Освен това, от урока за жизнения цикъл на обекта , вероятно си спомняте, че един обект съществува толкова дълго, колкото има поне една препратка към него. Ако не останат такива, обектът става плячка за боклукчия. Последователност от действия при създаване на обект - 2Тези първи две точки не трябва да повдигат специални въпроси. Разпределянето на памет е прост процес и има само два възможни изхода: or има памет, or я няма :) И създаването на връзка не е необичайно. Но третата точка представлява цял набор от операции, изпълнявани в строг ред. Не съм фен на тъпченето за тестове, но трябва да разберете добре този процес и трябва да запомните тази последователност от операции. Когато говорихме за процеса на създаване на обект в предишните уроци, все още не знаехте нищо за наследяването, така че обясняването на някои неща беше проблематично. Сега знаете доста и най-накрая можем да разгледаме този въпрос изцяло :) И така, третата точка гласи „ Накрая променливите се инициализират и конструкторът се извиква. “ Но в Howъв ред се случва всичко това? За по-добро разбиране нека създадем два супер прости класа — родител и дете:

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++; 
   } 
}
Класът Truckе реализация на камион с полета, представляващи неговата година, модел и максимална скорост. Сега искаме да създадем един такъв обект:

public class Main { 

   public static void main(String[] args) throws IOException { 

       Truck truck = new Truck(2017, "Scania S 500 4x2", 220); 
   } 
}
За Java машината процесът ще изглежда така:
  1. Първото нещо, което се случва е, че статичните променливи на Vehicleкласа се инициализират . Да, казах Vehicleкласа, не Truck. Статичните променливи се инициализират преди извикването на конструкторите и това започва в родителския клас. Нека се опитаме да проверим това. Задаваме vehicleCounterполето в Vehicleкласа равно на 10 и се опитваме да го покажем Howто в конструкторите, Vehicleтака и в Truckконструкторите.

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

    Съзнателно поставихме оператора println в самото начало на Truckконструктора, за да сме сигурни, че полетата на камиона все още не са инициализирани, когато vehicleCounterсе показва .

    И ето резултата:

    
    10 
    10
    
  2. След инициализиране на статичните променливи на родителския клас, статичните променливи на дъщерния клас се инициализират. В нашия случай това е truckCounterполето на Truckкласа.

    Нека направим друг експеримент, при който ще се опитаме да покажем стойността на truckCounterвътре в Truckконструктора, преди другите полета да бъдат инициализирани:

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

    Както можете да видите, стойността 10 вече е присвоена на нашата статична променлива, когато Truckконструкторът започне.

  3. Все още не е време за конструкторите! Инициализацията на променливата продължава. Нестатичните променливи на родителския клас се инициализират трети. Както можете да видите, наследяването значително усложнява процеса на създаване на обект, но нищо не можете да направите по въпроса: просто трябва да запомните някои неща в програмирането :)

    Като експеримент можем да присвоим няHowва първоначална стойност на descriptionпроменливата в Vehicleкласа и след това да я променим в конструктора.

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

    Нека стартираме нашия main()метод, който създава камион:

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

    Получаваме следния резултат:

    
    Initial value of the description field 
    Vehicle
    

    Това доказва, че когато Vehicleконструкторът започне, на descriptionполето вече е присвоена стойност.

  4. Най-накрая дойде време за конструкторите! По-точно, време е за конструктора на базов клас. Той се извиква в четвъртата стъпка от процеса на създаване на обект.

    Това също е доста лесно да се провери. Нека опитаме да изведем два реда към конзолата: единият вътре в Vehicleконструктора на базовия клас, вторият вътре в Truckконструктора. Трябва да сме убедени, че редът вътре Vehicleсе показва първо:

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

    Ще изпълним нашия main()метод и ще видим резултата:

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

    Отлично. Това означава, че не сме сбъркали :) Да продължим.

  5. Сега е време за инициализация на нестатичните полета на дъщерния клас, т.е. на нашия Truckклас. Полетата непосредствено в инстанцирания клас не се инициализират до петата стъпка! Изненадващо, но вярно :) Отново ще направим проста проверка — точно Howто с родителския клас: ще зададем няHowва начална стойност на променливата maxSpeedи в Truckконструктора ще проверим дали стойността е била присвоена преди стартирането на конструктора:

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

    Конзолен изход:

    
    Initial value of maxSpeed = 150
    

    Както можете да видите,  когато Truck конструкторът стартира, maxSpeed вече е равно на 150!

  6. TruckИзвиква се конструкторът на дъщерния клас.

    И едва в този момент, на последно място, ще бъде извикан конструкторът на класа, който инстанцираме!

    Само в шестата стъпка на полетата ще бъдат присвоени стойностите, които предаваме като аргументи на нашия камион.

    Както можете да видите, "конструирането" на камион, т.е. процесът на създаване на обект, не е лесен. Но изглежда, че сме го разделor на най-малки части :)

Последователност от действия при създаване на обект - 3 Защо е толкова важно да разберем добре този процес? Представете си колко неочаквани могат да бъдат резултатите от създаването на обикновен обект, ако не знаете точно Howво се случва „под капака“ :) Сега е време да се върнете към курса и да изпълните някои задачи! Успех и до скоро! :)
Коментари
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION