CodeGym /Java Blog /Random /Pagpapalawak at pagpapaliit ng mga uri ng sanggunian
John Squirrels
Antas
San Francisco

Pagpapalawak at pagpapaliit ng mga uri ng sanggunian

Nai-publish sa grupo
Hi! Sa isang nakaraang aralin, tinalakay namin ang paghahagis ng mga primitive na uri. Alalahanin natin sandali ang napag-usapan. Pagpapalawak at pagpapaliit ng mga uri ng sanggunian - 1Naisip namin ang mga primitive na uri (sa kasong ito, mga numeric na uri) bilang mga nesting doll na nag-iiba-iba ang laki ayon sa dami ng memory na nasasakop ng mga ito. Tulad ng maaalala mo, ang paglalagay ng isang mas maliit na manika sa loob ng isang mas malaki ay simple pareho sa totoong buhay at sa Java programming.

public class Main {
   public static void main(String[] args) {
       int bigNumber = 10000000;
       short smallNumber = (short) bigNumber;
       System.out.println(smallNumber);
   }
}
Ito ay isang halimbawa ng awtomatikong conversion o pagpapalawak . Nangyayari ito nang mag-isa, kaya hindi mo kailangang magsulat ng karagdagang code. Sa huli, wala kaming ginagawang kakaiba: nilalagay lang namin ang isang mas maliit na manika sa isang mas malaking manika. Isa pang bagay kung susubukan nating gawin ang kabaligtaran at ilagay ang isang mas malaking Russian na manika sa isang mas maliit na manika. Hindi mo magagawa iyon sa totoong buhay, ngunit sa programming magagawa mo. Ngunit may isang nuance. Kung susubukan naming ilagay ang isang intsa isang shortvariable, ang mga bagay ay hindi pumunta nang maayos para sa amin. Pagkatapos ng lahat, ang shortvariable ay nagtataglay lamang ng 16 na piraso ng impormasyon, ngunit ang isang intsumasakop sa 32 bits! Bilang resulta, ang naipasa na halaga ay nasira. Bibigyan tayo ng compiler ng error (' Dude, may ginagawa kang kahina-hinala!'). Ngunit kung tahasan naming ipahiwatig ang uri kung saan namin kino-convert ang aming halaga, magpapatuloy ito at isasagawa ang operasyon.

public class Main {

   public static void main(String[] args) {

       int bigNumber = 10000000;

       bigNumber = (short) bigNumber;

       System.out.println(bigNumber);

   }

}
Iyon lang ang ginawa namin sa halimbawa sa itaas. Ginawa ang operasyon, ngunit dahil ang shortvariable ay maaaring tumanggap lamang ng 16 sa 32 byte, ang panghuling halaga ay nasira at nakuha namin ang numero -27008 . Ang ganitong operasyon ay tinatawag na tahasang conversion, o pagpapaliit .

Mga halimbawa ng pagpapalawak at pagpapaliit ng mga uri ng sanggunian

Ngayon pag-usapan natin ang parehong mga operator na inilapat hindi sa mga primitive na uri, ngunit sa mga bagay at reference variable ! Paano ito gumagana sa Java? Ito ay talagang medyo simple. May mga bagay na walang kaugnayan. Magiging lohikal na ipagpalagay na hindi sila maaaring ma-convert sa isa't isa, alinman sa tahasan o awtomatiko:

public class Cat {
}

public class Dog {
}

public class Main {

   public static void main(String[] args) {

       Cat cat = new Dog(); // Error!

   }

}
Dito, siyempre, nakakakuha tayo ng isang error. Ang Catat Dogmga klase ay hindi nauugnay sa isa't isa, at hindi kami nagsulat ng 'converter' upang lumipat mula sa isa patungo sa isa pa. Makatuwiran na hindi natin ito magagawa: walang ideya ang compiler kung paano i-convert ang mga bagay na ito mula sa isang uri patungo sa isa pa. Kung ang mga bagay ay magkakaugnay, mabuti, iyan ay ibang usapan! Kaugnay paano? Higit sa lahat, sa pamamagitan ng mana. Subukan nating gumamit ng inheritance upang lumikha ng isang maliit na sistema ng mga klase. Magkakaroon tayo ng isang karaniwang klase upang kumatawan sa mga hayop:

public class Animal {

   public void introduce() {

       System.out.println("I'm Animal");
   }
}
Alam ng lahat na ang mga hayop ay maaaring alagang hayop (mga alagang hayop) o ligaw:

public class WildAnimal extends Animal {

   public void introduce() {

       System.out.println("I'm WildAnimal");
   }
}

public class Pet extends Animal {

   public void introduce() {

       System.out.println("I'm Pet");
   }
}
Halimbawa, kumuha ng mga canine — mayroon kaming mga alagang aso at coyote:

public class Dog extends Pet {

   public void introduce() {

       System.out.println("I'm Dog");
   }
}



public class Coyote extends WildAnimal {

   public void introduce() {

       System.out.println ("I'm Coyote");
   }
}
Partikular naming pinili ang pinakapangunahing mga klase para mas madaling maunawaan ang mga ito. Hindi talaga namin kailangan ng anumang field, at sapat na ang isang paraan. Subukan nating isagawa ang code na ito:

public class Main {

   public static void main(String[] args) {

       Animal animal = new Pet();
       animal.introduce();
   }
}
Ano sa palagay mo ang ipapakita sa console? Ang introduceparaan ba ng Petklase o Animalklase ay ipapatawag? Subukang bigyang-katwiran ang iyong sagot bago ka magpatuloy sa pagbabasa. At narito ang resulta! I'm Pet Bakit natin nakuha yan? Simple lang lahat. Mayroon kaming parent variable at descendant object. Sa pamamagitan ng pagsusulat,

Animal animal = new Pet();
pinalawakPet namin ang isang sanggunian at itinalaga ito sa isang Animalvariable. Tulad ng mga primitive na uri, ang mga uri ng sanggunian ay awtomatikong pinalalawak sa Java. Hindi mo kailangang magsulat ng karagdagang code para magawa ito. Ngayon ay mayroon kaming descendant object na itinalaga sa isang reference ng magulang. Bilang resulta, nakikita namin na ang tawag sa pamamaraan ay ginawa sa descendant class. Kung hindi mo pa rin lubos na nauunawaan kung bakit gumagana ang code na ito, muling isulat ito sa simpleng wika:

Animal animal = new DomesticatedAnimal();
Wala namang problema dito diba? Isipin na ito ay totoong buhay, at ang reference ay isang papel na label na may nakasulat na 'Animal'. Kung kukunin mo ang piraso ng papel na iyon at ilakip ito sa kwelyo ng anumang alagang hayop, magiging tama ang lahat. Pagkatapos ng lahat, ang anumang alagang hayop ay isang hayop! Ang baligtad na proseso — ang paglipat pababa sa puno ng mana sa mga inapo — ay lumiliit:

public class Main {

   public static void main(String[] args) {

       WildAnimal wildAnimal = new Coyote();

       Coyote coyote = (Coyote) wildAnimal;

       coyote.introduce();
   }
}
Tulad ng makikita mo, dito malinaw naming ipinapahiwatig ang klase kung saan gusto naming i-convert ang aming object. Dati kaming may WildAnimalvariable, at ngayon mayroon kaming Coyote, na mas mababa sa inheritance tree. Makatuwiran na nang walang tahasang indikasyon ay hindi papayagan ng compiler ang naturang operasyon, ngunit kung ipahiwatig namin ang uri sa mga panaklong, kung gayon ang lahat ay gagana. Pagpapalawak at pagpapaliit ng mga uri ng sanggunian - 2Isaalang-alang ang isa pang mas kawili-wiling halimbawa:

public class Main {

   public static void main(String[] args) {

       Pet pet = new Animal(); // Error!
   }
}
Ang compiler ay bumubuo ng isang error! Pero bakit? Dahil sinusubukan mong magtalaga ng parent object sa isang descendant reference. Sa madaling salita, sinusubukan mong gawin ang isang bagay tulad nito:

DomesticatedAnimal domesticatedAnimal = new Animal();
Well, siguro lahat ay gagana kung tahasan naming tukuyin ang uri na sinusubukan naming i-convert? Nakatulong iyon sa mga numero — Subukan natin! :)

public class Main {

   public static void main(String[] args) {

       Pet pet = (Pet) new Animal();
   }
}
Exception sa thread na "main" java.lang.ClassCastException: Hindi maaaring i-cast ang hayop sa Pet Error! Hindi kami sinigawan ng compiler sa oras na ito, ngunit nauwi kami sa isang pagbubukod. Alam na namin ang dahilan: sinusubukan naming magtalaga ng parent object sa isang descendant reference. Ngunit bakit eksaktong hindi mo magawa iyon? Dahil hindi lahat ng Hayop ay DomesticatedAnimals. Gumawa ka ng isang Animalbagay at sinusubukan mong italaga ito sa isang Petvariable. Ang coyote ay isa ding Animal, ngunit hindi ito isang Pet. Sa madaling salita, kapag nagsusulat ka

Pet pet = (Pet) new Animal();
new Animal()maaaring kumatawan sa anumang hayop, hindi kinakailangang isang alagang hayop! Natural, ang iyong Pet petvariable ay angkop lamang para sa pag-iimbak ng Mga Alagang Hayop (at ang kanilang mga inapo) at hindi sa anumang uri ng hayop. ClassCastExceptionIyon ang dahilan kung bakit nilikha ang isang espesyal na pagbubukod sa Java, , para sa mga kaso kung saan may naganap na error habang nag-cast ng mga klase. Suriin natin itong muli upang maging mas malinaw. Ang isang sanggunian ng magulang ay maaaring tumuro sa mga pagkakataon ng isang descendant na klase:

public class Main {

   public static void main(String[] args) {

       Pet pet = new Pet();
       Animal animal = pet;

       Pet pet2 = (Pet) animal;
       pet2.introduce();
   }
}
Halimbawa, dito wala tayong problema. Mayroon kaming isang Petbagay na tinutukoy ng isang Petvariable. Nang maglaon, Animalitinuro ng isang sanggunian ang mismong bagay. Pagkatapos nito, nagko-convert kami animalsa isang Pet. Oo nga pala, bakit ito gumana sa atin? Huling beses na nagkaroon kami ng exception! Dahil sa oras na ito ang aming orihinal na bagay ay isang Pet!

Pet pet = new Pet();
Ngunit sa huling halimbawa, ito ay isang Animalbagay:

Pet pet = (Pet) new Animal();
Hindi ka maaaring magtalaga ng ancestor object sa isang descendant variable. Maaari mong gawin ang kabaligtaran.
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION