JavaRush /Java blogi /Random-UZ /Malumot turlarining kengayishi va qisqarishi

Malumot turlarining kengayishi va qisqarishi

Guruhda nashr etilgan
Salom! Oldingi ma'ruzalardan birida biz ibtidoiy tiplarni kasting qilishni muhokama qildik. Keling, nima haqida gaplashayotganimizni qisqacha eslaylik. Malumot turlarining kengayishi va qisqarishi - 1Biz ibtidoiy turlarni (bu holda, raqamli) ular egallagan xotira miqdoriga ko'ra uyalar qo'g'irchoqlari sifatida taqdim etdik. Esingizda bo'lsa, kichikroq uyali qo'g'irchoqni kattaroq qo'g'irchoqqa joylashtirish haqiqiy hayotda ham, Java dasturlashda ham oddiy bo'ladi.
public class Main {
   public static void main(String[] args) {
        short smallNumber = 100;
        int bigNumber =  smallNumber;
        System.out.println(bigNumber);
   }
}
Bu avtomatik konvertatsiya yoki kengaytmaga misol . Bu o'z-o'zidan sodir bo'ladi, shuning uchun qo'shimcha kod yozishning hojati yo'q. Oxir-oqibat, biz hech qanday g'ayrioddiy ish qilmayapmiz: biz shunchaki kichikroq qo'g'irchoqni kattaroq qo'g'irchoqqa joylashtiramiz. Agar biz teskarisini qilishga harakat qilsak va katta matryoshka qo'g'irchog'ini kichikroq qilib qo'ysak, bu boshqa masala. Hayotda buni amalga oshirish mumkin emas, lekin dasturlashda buni qilish mumkin. Ammo bitta ogohlantirish bor. intAgar biz o'zgaruvchiga qiymat qo'yishga harakat qilsak short, bu oson ishlamaydi. Axir, o'zgaruvchiga faqat 16 bit ma'lumot sig'ishi mumkin short, ammo qiymat int32 bitni oladi! Natijada, uzatilgan qiymat buziladi. Kompilyator bizga xato beradi (“ do'stim, siz shubhali ish qilyapsiz! ”), lekin agar biz qiymatimizni qaysi turga o'tkazayotganimizni aniq ko'rsatsak, u hali ham shunday operatsiyani bajaradi.
public class Main {

   public static void main(String[] args) {

       int bigNumber = 10000000;

       bigNumber = (short) bigNumber;

       System.out.println(bigNumber);

   }

}
Yuqoridagi misolda biz buni qildik. Amaliyot tugallandi, lekin short32 bitdan faqat 16 tasi o'zgaruvchiga to'g'ri kelganligi sababli, yakuniy qiymat buzildi va natijada biz -27008 raqamini oldik . Ushbu operatsiya aniq konvertatsiya yoki toraytirish deb ataladi .

Malumot turlarining kengayishi va qisqarishiga misollar

Endi biz bir xil operatsiyalar haqida gapiramiz, lekin ibtidoiy turlarga emas, balki ob'ektlar va mos yozuvlar o'zgaruvchilarga nisbatan qo'llaniladi ! Bu Java'da qanday ishlaydi? Aslida juda oddiy. Bir-biriga bog'liq bo'lmagan ob'ektlar mavjud. Ularni bir-biriga aniq yoki avtomatik ravishda aylantirib bo'lmaydi deb taxmin qilish mantiqan to'g'ri bo'ladi:
public class Cat {
}

public class Dog {
}

public class Main {

   public static void main(String[] args) {

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

   }

}
Bu erda biz, albatta, xatoga yo'l qo'yamiz. Sinflar bir-biriga bog'liq Catemas Dogva biz bir-biridan boshqasiga "konvertor" yozmadik. Biz buni qila olmasligimiz mantiqan to'g'ri: kompilyator bu ob'ektlarni bir-biriga qanday aylantirishni bilmaydi. Ob'ektlar bir-biriga ulangan bo'lsa, bu boshqa masala! Qanaqasiga? Avvalo, merosdan foydalanish. Keling, meros bilan kichik sinf tizimini yaratishga harakat qilaylik. Biz hayvonlarni ifodalovchi umumiy sinfga ega bo'lamiz:
public class Animal {

   public void introduce() {

       System.out.println("i'm Animal");
   }
}
Ma'lumki, hayvonlar uy va yovvoyi hisoblanadi:
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");
   }
}
Masalan, itlarni olaylik - uy iti va koyot:
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");
   }
}
Bizning sinflarimiz ularni idrok etishni osonlashtirish uchun ataylab eng ibtidoiydir. Bu erda bizga maydonlar kerak emas va bitta usul etarli. Keling, quyidagi kodni ishga tushirishga harakat qilaylik:
public class Main {

   public static void main(String[] args) {

       Animal animal = new Pet();
       animal.introduce();
   }
}
Sizningcha, konsolga nima chiqadi? introduceSinf Petyoki sinf usuli ishlaydimi Animal? O'qishni davom ettirishdan oldin javobingizni asoslashga harakat qiling. Va bu erda natija! men uy hayvoniman, nega javob bu tarzda chiqdi? Hammasi oddiy. Bizda ota-o'zgaruvchi va bola ob'ekt mavjud. Yozish orqali:
Animal animal = new Pet();
Biz mos yozuvlar turini kengaytirdikPet va uning ob'ektini o'zgaruvchida saqladik Animal. Ibtidoiy turlarda bo'lgani kabi, Java-da mos yozuvlar turlarini kengaytirish avtomatik ravishda amalga oshiriladi. Buning uchun qo'shimcha kod yozishning hojati yo'q. Endi bizda ota-ona havolasiga biriktirilgan bola ob'ekti bor va natijada biz usul bolalar sinfida chaqirilganligini ko'ramiz. Agar siz hali ham ushbu kod nima uchun ishlashini to'liq tushunmasangiz, uni oddiy tilda qayta yozing:
Животное животное = new ДомашнееЖивотное();
Bu bilan hech qanday muammo yo'q, to'g'rimi? Tasavvur qiling-a, bu haqiqiy hayot va bu holda havola "Hayvon" deb yozilgan oddiy qog'oz yorlig'idir. Agar siz bunday qog'ozni olib, uni har qanday uy hayvonining yoqasiga biriktirsangiz, hamma narsa yaxshi bo'ladi. Har qanday uy hayvonlari hali ham hayvondir! Teskari jarayon, ya'ni meros daraxtini merosxo'rlarga o'tkazish torayishdir:
public class Main {

   public static void main(String[] args) {

       WildAnimal wildAnimal = new Coyote();

       Coyote coyote = (Coyote) wildAnimal;

       coyote.introduce();
   }
}
Ko'rib turganingizdek, bu erda biz ob'ektimizni qaysi sinfga o'tkazmoqchi ekanligimizni aniq ko'rsatamiz. Ilgari bizda o'zgaruvchi bor edi WildAnimal, endi esa Coyotemeros daraxtiga tushadi. Kompilyator bunday operatsiyani aniq ko'rsatmasdan o'tkazib yubormasligi mantiqan to'g'ri, lekin agar siz qavs ichida turni ko'rsatsangiz, hamma narsa ishlaydi. Malumot turlarining kengayishi va qisqarishi - 2 Keling, boshqa qiziqarli misolni ko'rib chiqaylik:
public class Main {

   public static void main(String[] args) {

       Pet pet = new Animal();//error!
   }
}
Kompilyator xatoga yo'l qo'yadi! Sababi nima? Haqiqat shundaki, siz asosiy o'zgaruvchiga ota-ona ob'ektini belgilashga harakat qilyapsiz. Boshqacha qilib aytganda, siz buni qilmoqchisiz:
ДомашнееЖивотное домашнееЖивотное = new Животное();
Ammo, ehtimol, biz qaysi turni aniq ko'rsatsak, muvaffaqiyatga erishamizmi? Raqamlar ishlayotganga o'xshaydi, sinab ko'raylik! :)
public class Main {

   public static void main(String[] args) {

       Pet pet = (Pet) new Animal();
   }
}
"Asosiy" java.lang.ClassCastException mavzusidagi istisno: Hayvonni Pet Xatosiga o'tkazib bo'lmaydi ! Kompilyator bu safar shikoyat qilmadi, ammo natijada biz istisno oldik. Buning sababini allaqachon bilamiz: biz asosiy o'zgaruvchiga ota-ona ob'ektini belgilashga harakat qilmoqdamiz. Nima uchun, aslida, buni amalga oshirish mumkin emas? Chunki hamma hayvonlar ham uy hayvonlari emas. Siz ob'ekt yaratdingiz Animalva uni o'zgaruvchiga belgilashga harakat qilyapsiz Pet. Ammo, masalan, koyot ham uy hayvonidir Animal, lekin u emas . PetBoshqacha qilib aytganda, siz yozganingizda:
Pet pet = (Pet) new Animal();
U erda new Animal()har qanday hayvon bo'lishi mumkin va u uy hayvonlari bo'lishi shart emas! Tabiiyki, sizning o'zgaruvchingiz Pet petfaqat uy hayvonlarini (va ularning avlodlarini) saqlash uchun mos keladi va hamma uchun emas. Shuning uchun, bunday holatlar uchun Java-da maxsus istisno yaratilgan - ClassCastExceptionsinflarni uzatishda xatolik. Aniqroq bo'lishi uchun yana bir bor aytaylik. Ota-o'zgaruvchi (mos yozuvlar) avlod sinfining ob'ektiga ishora qilishi mumkin:
public class Main {

   public static void main(String[] args) {

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

       Pet pet2 = (Pet) animal;
       pet2.introduce();
   }
}
Misol uchun, bu erda bizda hech qanday muammo bo'lmaydi. PetBizda havola bilan ko'rsatilgan ob'ekt bor Pet. Keyin yangi havola xuddi shu ob'ektga ishora qila boshladi Animal. Shundan so'ng biz konvertatsiya animalqilamiz Pet. Aytgancha, nega bunday qildik? Oxirgi marta bizda istisno bor edi! Chunki bu safar bizning asl ob'ektimiz Pet pet!
Pet pet =  new Pet();
Va oldingi misolda bu ob'ekt edi Animal:
Pet pet = (Pet) new Animal();
Avlod o'zgaruvchiga ajdod ob'ektini belgilash mumkin emas. Aksincha, siz buni qila olasiz.
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION