JavaRush /Java Blog /Random-TL /Pagpapalawak at pagliit ng mga uri ng sanggunian

Pagpapalawak at pagliit ng mga uri ng sanggunian

Nai-publish sa grupo
Kamusta! Sa isa sa mga nakaraang lektura, tinalakay namin ang paghahagis ng mga primitive na uri. Alalahanin natin sandali kung ano ang pinag-uusapan natin. Pagpapalawak at pagliit ng mga uri ng sanggunian - 1Kinakatawan namin ang mga primitive na uri (sa kasong ito, numeric) bilang mga nesting doll ayon sa dami ng memory na nasasakop nila. Tulad ng naaalala mo, ang paglalagay ng isang mas maliit na nesting doll sa isang mas malaki ay magiging simple pareho sa totoong buhay at sa Java programming.
public class Main {
   public static void main(String[] args) {
        short smallNumber = 100;
        int bigNumber =  smallNumber;
        System.out.println(bigNumber);
   }
}
Ito ay isang halimbawa ng awtomatikong conversion, o extension . Nangyayari ito sa sarili nitong, kaya hindi na kailangang magsulat ng karagdagang code. Sa huli, wala kaming ginagawang kakaiba: inilalagay lang namin ang isang mas maliit na nesting doll sa isang mas malaking nesting doll. Ito ay isa pang bagay kung susubukan nating gawin ang kabaligtaran at ilagay ang isang malaking matryoshka na manika sa isang mas maliit. Hindi ito magagawa sa buhay, ngunit sa pagprograma ito ay magagawa. Ngunit mayroong isang caveat. Kung susubukan naming ilagay ang isang halaga intsa isang variable short, hindi ito gagana nang ganoon kadali. Pagkatapos ng lahat, 16 na piraso lang ng impormasyon ang maaaring magkasya sa isang variable short, ngunit ang halaga intay tumatagal ng 32 bits! Bilang resulta, ang ipinadala na halaga ay mababaluktot. Bibigyan tayo ng compiler ng error (“ dude, may ginagawa kang kahina-hinala! ”), ngunit kung tahasan nating tutukuyin kung anong uri ang paglalagay ng value natin, magsasagawa pa rin ito ng ganoong operasyon.
public class Main {

   public static void main(String[] args) {

       int bigNumber = 10000000;

       bigNumber = (short) bigNumber;

       System.out.println(bigNumber);

   }

}
Sa halimbawa sa itaas, ginawa namin iyon. Nakumpleto ang operasyon, ngunit dahil short16 lamang sa 32 bits ang umaangkop sa variable, ang panghuling halaga ay nasira, at bilang resulta natanggap namin ang numero -27008 . Ang operasyong ito ay tinatawag na tahasang conversion, o pagpapaliit .

Mga halimbawa ng extension at contraction ng mga uri ng sanggunian

Ngayon ay pag-uusapan natin ang tungkol sa parehong mga operasyon, ngunit naaangkop hindi sa mga primitive na uri, ngunit sa mga bagay at reference variable ! Paano ito gumagana sa Java? Medyo simple talaga. May mga bagay na hindi nauugnay sa isa't isa. Magiging lohikal na ipagpalagay na hindi sila mako-convert sa isa't isa nang 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, makakakuha tayo ng isang error. Ang mga klase Catay Doghindi nauugnay sa isa't isa, at hindi kami nagsulat ng "converter" mula sa isa't isa. Lohikal na hindi namin magagawa ito: walang ideya ang compiler kung paano i-convert ang mga bagay na ito sa pagitan ng isa't isa. Isa pang bagay kung ang mga bagay ay konektado sa isa't isa! Paano? Una sa lahat, gamit ang mana. Subukan nating lumikha ng isang maliit na sistema ng klase na may mana. Magkakaroon tayo ng pangkalahatang klase na kumakatawan sa mga hayop:
public class Animal {

   public void introduce() {

       System.out.println("i'm Animal");
   }
}
Ang mga hayop, tulad ng alam mo, ay domestic at wild:
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 tayo ng mga aso - isang alagang aso at isang 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");
   }
}
Ang aming mga klase ay sadyang pinaka-primitive upang gawing mas madaling maunawaan ang mga ito. Hindi talaga namin kailangan ang mga field dito, at sapat na ang isang paraan. Subukan nating patakbuhin ang sumusunod na code:
public class Main {

   public static void main(String[] args) {

       Animal animal = new Pet();
       animal.introduce();
   }
}
Ano sa tingin mo ang magiging output sa console? Gagana ba ang paraan introduceng klase Peto klase Animal? Subukang bigyang-katwiran ang iyong sagot bago magpatuloy sa pagbabasa. At narito ang resulta! i'm Pet Bakit naging ganito ang sagot? Simple lang. Mayroon kaming variable ng magulang at object ng bata. Sa pamamagitan ng pagsulat:
Animal animal = new Pet();
Pinalawak namin ang isang uri ng sanggunianPet at inimbak ang bagay nito sa isang variable Animal. Tulad ng mga primitive na uri, ang extension ng mga uri ng reference sa Java ay awtomatikong ginagawa. Hindi na kailangang magsulat ng karagdagang code para dito. Ngayon ay mayroon kaming child object na naka-attach sa reference ng magulang, at bilang isang resulta nakita namin na ang pamamaraan ay tinatawag sa klase ng bata. Kung hindi mo pa rin lubos na nauunawaan kung bakit gumagana ang code na ito, muling isulat ito sa simpleng wika:
Животное животное = new ДомашнееЖивотное();
Wala namang problema di ba? Isipin na ito ay totoong buhay, at ang link sa kasong ito ay isang simpleng papel na tag na nagsasabing "Animal." Kung kukuha ka ng ganoong piraso ng papel at ilakip ito sa kwelyo ng anumang alagang hayop, magiging maayos ang lahat. Kahit anong alagang hayop ay hayop pa rin! Ang kabaligtaran na proseso, iyon ay, ang paglipat pababa sa puno ng mana sa mga tagapagmana, ay isang pagpapaliit:
public class Main {

   public static void main(String[] args) {

       WildAnimal wildAnimal = new Coyote();

       Coyote coyote = (Coyote) wildAnimal;

       coyote.introduce();
   }
}
Gaya ng nakikita mo, dito ay tahasan naming ipinapahiwatig kung saang klase namin gustong ihagis ang aming object. Dati mayroon kaming variable WildAnimal, at ngayon Coyote, na bumababa sa inheritance tree. Ito ay lohikal na ang compiler ay hindi laktawan ang naturang operasyon nang walang tahasang indikasyon, ngunit kung tinukoy mo ang uri sa mga panaklong, lahat ay gagana. Pagpapalawak at pagliit ng mga uri ng sanggunian - 2 Tingnan natin ang isa pang halimbawa, mas kawili-wili:
public class Main {

   public static void main(String[] args) {

       Pet pet = new Animal();//error!
   }
}
Ang compiler ay nagtatapon ng isang error! Ano ang dahilan? Ang katotohanan ay sinusubukan mong magtalaga ng isang magulang na bagay sa isang variable ng bata. Sa madaling salita, gusto mong gawin ito:
ДомашнееЖивотное домашнееЖивотное = new Животное();
Ngunit marahil kung tahasan nating ipahiwatig ang uri na sinusubukan nating i-cast, magtatagumpay tayo? Mukhang gumagana ang mga numero, subukan natin ito! :)
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! Ang compiler ay hindi nagreklamo sa oras na ito, ngunit bilang isang resulta nakatanggap kami ng isang pagbubukod. Alam na namin ang dahilan: sinusubukan naming magtalaga ng parent object sa isang child variable. Bakit, sa katunayan, hindi ito magagawa? Dahil hindi lahat ng Hayop ay Alagang Hayop. Gumawa ka ng isang bagay Animalat sinusubukan mong italaga ito sa isang variable Pet. Ngunit, halimbawa, ang coyote ay Animal, ngunit hindi ito Pet, isang alagang hayop. Sa madaling salita, kapag sumulat ka:
Pet pet = (Pet) new Animal();
new Animal()Ang anumang hayop ay maaaring naroroon , at hindi ito kailangang maging domestic! Natural, ang iyong variable Pet petay angkop lamang para sa pag-iimbak ng mga alagang hayop (at ang kanilang mga inapo), at hindi para sa lahat. Samakatuwid, para sa mga ganitong kaso, isang espesyal na pagbubukod ang nilikha sa Java - ClassCastExceptionisang error kapag nag-cast ng mga klase. Ulitin natin para mas malinaw. Maaaring tumuro ang isang parent variable (reference) sa isang object ng descendant class:
public class Main {

   public static void main(String[] args) {

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

       Pet pet2 = (Pet) animal;
       pet2.introduce();
   }
}
Halimbawa, hindi kami magkakaroon ng anumang mga problema dito. Mayroon kaming isang bagay Petna itinuturo ng isang link Pet. Pagkatapos ay nagsimula ang isang bagong link na tumuro sa parehong bagay Animal. Pagkatapos nito ginagawa namin ang conversion animalsa Pet. Bakit namin ginawa ito, sa pamamagitan ng paraan? Huling beses na nagkaroon kami ng exception! Dahil sa oras na ito ang aming orihinal na bagay ay Pet pet!
Pet pet =  new Pet();
At sa nakaraang halimbawa ito ay isang bagay Animal:
Pet pet = (Pet) new Animal();
Ang isang descendant variable ay hindi maaaring magtalaga ng ancestor object. Sa kabaligtaran, magagawa mo ito.
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION