JavaRush /Java Blog /Random-TL /Mga konstruktor sa Java

Mga konstruktor sa Java

Nai-publish sa grupo
Kamusta! Ngayon ay titingnan natin ang isang napakahalagang paksa na may kinalaman sa ating mga bagay. Dito, nang walang pagmamalabis, masasabi nating gagamitin mo ang kaalamang ito araw-araw sa totoong trabaho! Pag-uusapan natin ang tungkol sa mga konstruktor. Maaaring narinig mo ang terminong ito sa unang pagkakataon, ngunit sa katunayan malamang na gumamit ka ng mga konstruktor, ngunit hindi mo lang napansin ito mismo :) Makikita natin ito mamaya.

Ano ang isang constructor sa Java at bakit ito kailangan?

Tingnan natin ang dalawang halimbawa.
public class Car {

   String model;
   int maxSpeed;

   public static void main(String[] args) {

       Car bugatti = new Car();
       bugatti.model = "Bugatti Veyron";
       bugatti.maxSpeed = 407;

   }
}
Ginawa namin ang aming sasakyan at itinakda ang modelo at pinakamataas na bilis nito. Gayunpaman, sa isang tunay na proyekto, ang object ng Kotse ay malinaw na magkakaroon ng higit sa 2 field. At, halimbawa, 16 na mga patlang!
public class Car {

   String model;//model
   int maxSpeed;//max speed
   int wheels;// disk width
   double engineVolume;//engine capacity
   String color;//color
   int yearOfIssue;//year of issue
   String ownerFirstName;//Owner's name
   String ownerLastName;//owner's last name
   long price;//price
   boolean isNew;//new or not
   int placesInTheSalon;//number of seats in the cabin
   String salonMaterial;// interior material
   boolean insurance;//is it insured
   String manufacturerCountry;//manufacturer country
   int trunkVolume;// trunk volume
   int accelerationTo100km;//acceleration to 100 km/h in seconds


   public static void main(String[] args) {
       Car bugatti = new Car();

       bugatti.color = "blue";
       bugatti.accelerationTo100km = 3;
       bugatti.engineVolume = 6.3;
       bugatti.manufacturerCountry = "Italy";
       bugatti.ownerFirstName = "Amigo";
       bugatti.yearOfIssue = 2016;
       bugatti.insurance = true;
       bugatti.price = 2000000;
       bugatti.isNew = false;
       bugatti.placesInTheSalon = 2;
       bugatti.maxSpeed = 407;
       bugatti.model = "Bugatti Veyron";

   }

}
Gumawa kami ng bagong bagay sa Kotse . Isang problema: mayroon kaming 16 na field, ngunit 12 lang ang nasimulan namin ! Subukan ngayon gamit ang code upang mahanap ang mga nakalimutan namin! Hindi ganoon kadali, tama ba? Sa ganoong sitwasyon, ang programmer ay madaling magkamali at laktawan ang pagsisimula ng ilang field. Bilang resulta, ang pag-uugali ng programa ay magiging mali:
public class Car {

   String model;//model
   int maxSpeed;//max speed
   int wheels;// disk width
   double engineVolume;//engine capacity
   String color;//color
   int yearOfIssue;//year of issue
   String ownerFirstName;//Owner's name
   String ownerLastName;//owner's last name
   long price;//price
   boolean isNew;//new or not
   int placesInTheSalon;//number of seats in the cabin
   String salonMaterial;// interior material
   boolean insurance;//is it insured
   String manufacturerCountry;//manufacturer country
   int trunkVolume;// trunk volume
   int accelerationTo100km;//acceleration to 100 km/h in seconds


   public static void main(String[] args) {
       Car bugatti = new Car();

       bugatti.color = "blue";
       bugatti.accelerationTo100km = 3;
       bugatti.engineVolume = 6.3;
       bugatti.manufacturerCountry = "Italy";
       bugatti.ownerFirstName = "Amigo";
       bugatti.yearOfIssue = 2016;
       bugatti.insurance = true;
       bugatti.price = 2000000;
       bugatti.isNew = false;
       bugatti.placesInTheSalon = 2;
       bugatti.maxSpeed = 407;
       bugatti.model = "Bugatti Veyron";

       System.out.println("Model Bugatti Veyron. Engine size - " + bugatti.engineVolume + ", trunk - " + bugatti.trunkVolume + ", salon is made of" + bugatti.salonMaterial +
       ", disc width - " + bugatti.wheels + ". Was acquired in 2018 by Mr. " + bugatti.ownerLastName);

   }

}
Output ng console:
Modelo ng Bugatti Veyron. Pag-alis ng makina - 6.3, trunk - 0, panloob na gawa sa null, lapad ng rim - 0. Binili noong 2018 ni G. null
Ang iyong bumibili, na nagbayad ng $2 milyon para sa isang kotse, ay halatang hindi magugustuhan na tawaging "Mr. Null"! Ngunit seryoso, sa huli, ang aming programa ay napunta sa isang maling nilikha na bagay - isang kotse na may lapad ng rim 0 (iyon ay, walang mga rims), isang nawawalang puno ng kahoy, isang panloob na gawa sa hindi kilalang materyal, at kahit na pag-aari ng isang hindi kilalang tao. . Maaari lamang isipin ng isa kung paano maaaring mangyari ang gayong error habang tumatakbo ang programa! Kailangan nating iwasan kahit papaano ang mga ganitong sitwasyon. Kailangan namin ang aming programa na magkaroon ng isang limitasyon: kapag lumilikha ng isang bagong object ng sasakyan, halimbawa, ang modelo at maximum na bilis ay dapat palaging tinukoy para dito. Kung hindi, huwag payagan ang paggawa ng bagay. Ang mga function ng constructor ay madaling makayanan ang gawaing ito. Nakuha nila ang kanilang pangalan para sa isang dahilan. Ang constructor ay lumilikha ng isang uri ng "skeleton" ng klase, kung saan ang bawat bagong bagay ng klase ay dapat tumugma. Para sa kaginhawahan, bumalik tayo sa isang mas simpleng bersyon ng klase ng Kotse na may dalawang field. Dahil sa aming mga kinakailangan, magiging ganito ang constructor para sa klase ng Kotse :
public Car(String model, int maxSpeed) {
   this.model = model;
   this.maxSpeed = maxSpeed;
}
At ang paglikha ng isang bagay ngayon ay ganito ang hitsura:
public static void main(String[] args) {
   Car bugatti = new Car("Bugatti Veyron", 407);
}
Bigyang-pansinkung paano nilikha ang tagabuo. Ito ay katulad ng isang regular na pamamaraan, ngunit wala itong uri ng pagbabalik. Sa kasong ito, ang pangalan ng klase ay ipinahiwatig sa constructor, na may malaking titik din. Sa aming kaso - Kotse . Bilang karagdagan, ginagamit ng tagabuo ang bagong-sa-iyo na keyword na ito . "ito" sa Ingles ay nangangahulugang "ito, ito". Ang salitang ito ay tumutukoy sa isang tiyak na bagay. Code sa constructor:
public Car(String model, int maxSpeed) {
   this.model = model;
   this.maxSpeed = maxSpeed;
}
maaaring isalin nang halos literal: " modelo para sa makinang ito (na ginagawa natin ngayon) = ang argumento ng modelo , na tinukoy sa tagabuo. maxSpeed ​​​​para sa makinang ito (na ating nililikha) = ang maxSpeed ​​​​argument , na ay tinukoy sa constructor." Ito ang nangyari:
public class Car {

   String model;
   int maxSpeed;

   public Car(String model, int maxSpeed) {
       this.model = model;
       this.maxSpeed = maxSpeed;
   }

   public static void main(String[] args) {
       Car bugatti = new Car("Bugatti Veyron", 407);
       System.out.println(bugatti.model);
       System.out.println(bugatti.maxSpeed);
   }

}
Output ng console:
Bugatti Veyron 407
Matagumpay na naitalaga ng tagabuo ang mga kinakailangang halaga. Maaaring napansin mo na ang isang tagabuo ay halos kapareho sa isang regular na pamamaraan! Iyan ay kung paano ito ay: isang constructor ay isang paraan, lamang ng isang maliit na tiyak :) Tulad ng sa isang paraan, kami ay nagpasa ng mga parameter sa aming constructor. At tulad ng pagtawag sa isang pamamaraan, ang pagtawag sa isang constructor ay hindi gagana kung hindi mo tinukoy ang mga ito:
public class Car {

   String model;
   int maxSpeed;

   public Car(String model, int maxSpeed) {
       this.model = model;
       this.maxSpeed = maxSpeed;
   }

   public static void main(String[] args) {
       Car bugatti = new Car(); //error!
   }

}
Nakikita mo, ginawa ng taga-disenyo ang sinusubukan naming makamit. Ngayon ay hindi ka makakagawa ng kotse nang walang bilis o walang modelo! Ang mga pagkakatulad sa pagitan ng mga konstruktor at mga pamamaraan ay hindi nagtatapos doon. Tulad ng mga pamamaraan, ang mga konstruktor ay maaaring ma-overload. Isipin na mayroon kang 2 pusa sa bahay. Kinuha mo ang isa sa kanila bilang isang kuting, at iniuwi mo ang pangalawa mula sa kalye bilang isang matanda at hindi mo alam kung gaano siya katanda. Nangangahulugan ito na ang aming programa ay dapat na makalikha ng mga pusa ng dalawang uri - na may pangalan at edad para sa unang pusa, at may pangalan lamang - para sa pangalawang pusa. Upang gawin ito, i-overload namin ang constructor:
public class Cat {

   String name;
   int age;

   //for the first cat
   public Cat(String name, int age) {
       this.name = name;
       this.age = age;
   }

   //for the second cat
   public Cat(String name) {
       this.name = name;
   }

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5);
       Cat streetCatNamedBob = new Cat("Bob");
   }

}
Sa orihinal na constructor na may mga parameter na "pangalan" at "edad", nagdagdag kami ng isa pa, na may pangalan lamang. Nag-overload kami ng mga pamamaraan sa parehong paraan sa mga nakaraang aralin. Ngayon ay matagumpay na nating magagawa ang parehong bersyon ng mga pusa :) Bakit kailangan ang mga konstruktor?  - 2Naaalala mo ba sa simula ng panayam na sinabi namin na gumamit ka na ng mga konstruktor, ngunit hindi mo lang napansin? Ito ay totoo. Ang katotohanan ay ang bawat klase sa Java ay may tinatawag na default constructor. Wala itong anumang mga argumento, ngunit nagpapaputok ito sa tuwing nagagawa ang anumang bagay ng anumang klase.
public class Cat {

   public static void main(String[] args) {

       Cat barsik = new Cat(); //this is where the default constructor worked
   }
}
Sa unang tingin ito ay hindi napapansin. Buweno, lumikha kami ng isang bagay at nilikha ito, nasaan ang gawa ng taga-disenyo? Upang makita ito, sumulat tayo ng isang walang laman na constructor para sa klase ng Cat gamit ang ating sariling mga kamay , at sa loob nito ay magpi-print tayo ng ilang parirala sa console. Kung ito ay ipinapakita, kung gayon ang tagabuo ay nagtrabaho.
public class Cat {

   public Cat() {
       System.out.println("Created a cat!");
   }

   public static void main(String[] args) {

       Cat barsik = new Cat(); //this is where the default constructor worked
   }
}
Output ng console:
Gumawa sila ng pusa!
Narito ang kumpirmasyon! Ang default na tagabuo ay palaging hindi nakikita sa iyong mga klase. Ngunit kailangan mong malaman ang isa pang tampok nito. Ang default na constructor ay nawawala sa klase kapag lumikha ka ng ilang constructor na may mga argumento. Ang patunay nito, sa katunayan, nakita na natin sa itaas. Dito sa code na ito:
public class Cat {

   String name;
   int age;

   public Cat(String name, int age) {
       this.name = name;
       this.age = age;
   }

   public static void main(String[] args) {

       Cat barsik = new Cat(); //error!
   }
}
Hindi kami makakagawa ng pusa nang walang pangalan at edad dahil tinukoy namin ang isang constructor para sa Cat : string + number. Ang default na tagabuo ay nawala mula sa klase kaagad pagkatapos nito. Samakatuwid, siguraduhing tandaan: kung kailangan mo ng ilang mga konstruktor sa iyong klase, kabilang ang isang walang laman, kailangan mong likhain ito nang hiwalay. Halimbawa, gumagawa kami ng isang programa para sa isang beterinaryo na klinika. Nais ng aming klinika na gumawa ng mabubuting gawa at tumulong sa mga pusang walang tirahan, na hindi namin alam ang pangalan o edad. Kung gayon ang aming code ay dapat magmukhang ganito:
public class Cat {

   String name;
   int age;

   //for domestic cats
   public Cat(String name, int age) {
       this.name = name;
       this.age = age;
   }

   //for street cats
   public Cat() {
   }

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5);
       Cat streetCat = new Cat();
   }
}
Ngayong tahasan na nating isinulat ang default na constructor, maaari tayong lumikha ng mga pusa ng parehong uri :) Para sa isang constructor (tulad ng para sa anumang pamamaraan), ang pagkakasunud-sunod ng mga argumento ay napakahalaga. Palitan natin ang mga argumento ng pangalan at edad sa ating constructor.
public class Cat {

   String name;
   int age;

   public Cat(int age, String name) {
       this.name = name;
       this.age = age;
   }

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 10); //error!
   }
}
Error! Ang constructor ay malinaw na nagsasaad na kapag ang isang Cat object ay nilikha, ito ay dapat na pumasa sa isang numero at isang string, sa ganoong pagkakasunud-sunod. Iyon ang dahilan kung bakit hindi gumagana ang aming code. Tiyaking tandaan ito at isaisip ito kapag gumagawa ng sarili mong mga klase:
public Cat(String name, int age) {
   this.name = name;
   this.age = age;
}

public Cat(int age, String name) {
   this.age = age;
   this.name = name;
}
Ito ay dalawang ganap na magkaibang mga designer! Kung ipahayag natin ang sagot sa tanong na "Bakit kailangan natin ng constructor?" sa isang pangungusap, masasabi natin: upang ang mga bagay ay palaging nasa tamang estado. Kapag gumamit ka ng mga constructor, ang lahat ng iyong mga variable ay tama ang pagsisimula, at walang mga kotse na may bilis na 0 o iba pang "maling" na mga bagay sa programa. Ang kanilang paggamit ay lubhang kapaki-pakinabang, una sa lahat, para sa programmer mismo. Kung ikaw mismo ang magsisimula ng mga field, may mataas na panganib na magkaroon ng kulang at magkamali. Ngunit hindi ito mangyayari sa isang tagabuo: kung hindi mo naipasa ang lahat ng kinakailangang mga argumento dito o pinaghalo ang kanilang mga uri, ang tagatala ay agad na magtapon ng isang error. Ito ay nagkakahalaga ng pagbanggit nang hiwalay na hindi mo dapat ilagay ang lohika ng iyong programa sa loob ng constructor. Upang gawin ito, mayroon kang mga pamamaraan na magagamit mo kung saan maaari mong ilarawan ang lahat ng pag-andar na kailangan mo. Tingnan natin kung bakit ang lohika ng constructor ay isang masamang ideya:
public class CarFactory {

   String name;
   int age;
   int carsCount;

   public CarFactory(String name, int age, int carsCount) {
   this.name = name;
   this.age = age;
   this.carsCount = carsCount;

   System.out.println("Our car factory is called" + this.name);
   System.out.println("She was founded" + this.age + " years ago" );
   System.out.println("During this time it was produced" + this.carsCount +  "cars");
   System.out.println("On average she produces" + (this.carsCount/this.age) + "cars per year");
}

   public static void main(String[] args) {

       CarFactory ford = new CarFactory("Ford", 115 , 50000000);
   }
}
Mayroon kaming klase ng CarFactory na naglalarawan ng isang pabrika para sa paggawa ng mga sasakyan. Sa loob ng constructor, sinisimulan namin ang lahat ng mga field at inilalagay ang logic dito: ipinapakita namin ang ilang impormasyon tungkol sa pabrika sa console. Mukhang walang mali dito, gumana nang perpekto ang programa. Output ng console:
Ang aming pabrika ng kotse ay tinatawag na Ford. Ito ay itinatag 115 taon na ang nakakaraan. Sa panahong ito, nakagawa ito ng 50,000,000 mga kotse. Sa karaniwan, gumagawa ito ng 434,782 na mga kotse bawat taon.
Pero sa totoo lang, nagtanim tayo ng time bomb. At ang naturang code ay napakadaling humantong sa mga error. Isipin natin na ngayon ay hindi natin pinag-uusapan ang tungkol sa Ford, ngunit tungkol sa bagong pabrika na "Amigo Motors", na umiral nang wala pang isang taon at nakagawa ng 1000 mga kotse:
public class CarFactory {

   String name;
   int age;
   int carsCount;

   public CarFactory(String name, int age, int carsCount) {
   this.name = name;
   this.age = age;
   this.carsCount = carsCount;

   System.out.println("Our car factory is called" + this.name);
   System.out.println("She was founded" + this.age + " years ago" );
   System.out.println("During this time it was produced" + this.carsCount +  "cars");
   System.out.println("On average she produces" + (this.carsCount/this.age) + "cars per year");
}


   public static void main(String[] args) {

       CarFactory ford = new CarFactory("Amigo Motors", 0 , 1000);
   }
}
Output ng console:
Ang aming pabrika ng sasakyan ay tinatawag na Amigo Motors Exception sa thread na "main" java.lang.ArithmeticException: / by zero Itinatag 0 taon na ang nakakaraan Sa panahong ito, gumawa ito ng 1000 sasakyan sa CarFactory.<init>(CarFactory.java:15) sa CarFactory.main(CarFactory.java:23) Natapos ang proseso gamit ang exit code 1</init>
Nakarating na kami! Natapos ang programa na may kakaibang error. Susubukan mo bang hulaan kung ano ang dahilan? Ang dahilan ay ang logic na inilagay namin sa constructor. Sa partikular, sa linyang ito:
System.out.println("On average she produces" + (this.carsCount/this.age) + "cars per year");
Dito ginagawa namin ang pagkalkula at hinahati ang bilang ng mga kotse na ginawa sa edad ng pabrika. At dahil ang aming pabrika ay bago (iyon ay, ito ay 0 taong gulang), ang resulta ay paghahati ng 0, na ipinagbabawal sa matematika. Bilang isang resulta, ang programa ay nagtatapos sa isang error. Ano ang dapat naming ginawa? Ilipat ang lahat ng lohika sa isang hiwalay na paraan at tawagan ito, halimbawa, printFactoryInfo() . Maaari mo itong ipasa sa isang CarFactory object bilang isang parameter . Maaari mo ring ilagay ang lahat ng lohika doon, at sa parehong oras - pagproseso ng mga posibleng error, tulad ng sa amin na may zero na taon. Sa kanya-kanyang sarili. Kinakailangan ang mga konstruktor upang maitakda nang tama ang estado ng isang bagay. Para sa lohika ng negosyo mayroon kaming mga pamamaraan. Hindi mo dapat ihalo ang isa sa isa.
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION