JavaRush /Kurslar /All lectures for UZ purposes /Java dagi Parametrli turlar – Generics

Java dagi Parametrli turlar – Generics

All lectures for UZ purposes
Daraja , Dars
Mavjud

1. Barcha classlar Object dan meros oladi

Java dagi barcha classlar yashirincha (pinhona) Object classidan meros oladi.

Meros olish nima va u Java da qanday ishlaydi, biz buni Java Core qismida tushunamiz. Hozir esa biz bu faktni muhokama qilamiz:

Object turidagi o'zgaruvchiga har qanday classning obyektini tayinlash mumkin. Misol:

Kod Izoh
Object o = new Scanner(System.in);
o o'zgaruvchisida Scanner turidagi obyektga ishora saqlangan
Object o = new String();
o o'zgaruvchisida String turidagi obyektga ishora saqlangan
Object o = new Integer(15);
o o'zgaruvchisida Integer turidagi obyektga ishora saqlangan
Object o = "Привет";
o o'zgaruvchisida String turidagi obyektga ishora saqlangan

Yaxshi yangiliklar shu yerda tugaydi. Kompyilator Object turidagi o'zgaruvchida qanday obyekt saqlanganini kuzatmaydi, shuning uchun saqlangan obyektning o'ziga xos funksiyalarini chaqirishning imkoni yo'q, agar ular Object turida mavjud bo'lmasa nasha.

Agar obyektning metodlarini chaqirish kerak bo'lsa, avvalo unga ishorani to'g'ri tipdagi o'zgaruvchiga saqlash kerak, so'ngra bu o'zgaruvchining metodlariga murojaat qilish mumkin:

Kod Izoh
Object o = new Scanner(System.in);
int x = o.nextInt();
Dastur kompilyatsiya qilinmaydi. Object classida nextInt() metodi yo'q.
Object o = new Scanner(System.in);

Scanner console = (Scanner) o;

int x = console.nextInt();
Bu ish qiladi.

Bu erda biz Scanner turidagi obyektga ishorani Scanner turidagi o'zgaruvchiga saqlaymiz turini qayta o'zgartirish operatori orqali.

Oddiy sharoitlarda Object turidagi o'zgaruvchini Scanner turidagi o'zgaruvchiga tayinlash mumkin emas, hatto agar Object turidagi o'zgaruvchi Scanner turidagi obyektga ishora qilsada. Lekin bu mumkin, agar siz allaqachon ma'lum bo'lgan turini qayta o'zgartirish operatorini ishlatsangiz. Umumiy ko'rinishda bu quyidagicha:

Tip nom1 = (Tip) nom2;

Bu yerda nom1 – bu Tip turidagi o'zgaruvchining nomi, va nom2 – bu Object turidagi o'zgaruvchining nomi, qaysiga Tip turidagi obyektga ishora saqlanmoqda.

Turini qayta o'zgartirish

Agar o'zgaruvchi va obyektnin turlari mos kelmasa, ClassCastException xatosi yuzaga kelishi mumkin. Misol:

Kod Izoh
Object o = new Integer(5);
String s = (String) o;
Ishlash paytida xato yuzaga keladi:
bu erda ClassCastException istisnosi tashlanadi

Java da bu xatoni oldini olishning bir usuli bor: o'zgaruvchida haqiqatda qanday tur saqlanganligini tekshirish usuli mavjud:

nom instanceof Tip

instanceof operatori nom o'zgaruvchining Tip turida obyekt ekanligini tekshiradi.

Misol — ma'lumotlar massivida matnni topish:

Kod Izoh
Object[] objects = {10, "Привет", 3.14};

for (int i = 0; i < objects.length; i++)
{
   if (objects[i] instanceof String)
   {
      String s = (String) objects[i];
      System.out.println(s);
   }
}
Autoboxing bu qiymatlar Integer, String va Double ga aylantiradi.

Ob'ektlar massivi orqali aylanish

Agar obyekt String turida bo'lsa

Uni String turidagi o'zgaruvchiga saqlash
O'zgaruvchini ekranga chiqarish.


2. Shablonlar yuzaga kelish sababi (kolleksiyalar)

Kolleksiyalarga qaytamiz.

Java ishlab chiquvchilari ArrayList klassini yaratishda, ular istalgan turdagi ob'ektlarni saqlash uchun uni universal qilishni xohlashdi. Shu sababli elementlarni saqlash uchun Object turidagi massivdan foydalandilar.

Bunday yondashuvning kuchli tomoni shundaki, kolleksiyaga istalgan turdagi ob'ekt qo'shish mumkin.

Lekin bir nechta kamchiliklar ham mavjud.

Kammentariy 1.

Kolleksiya elementlarini olishda har doim turini o'zgartirish operatorini yozishga to'g'ri kelardi:

Kod Izoh
ArrayList numbers = new ArrayList();


for (int i = 0; i < 10; i++)
   numbers.add(i * 10);


int sum = 0;
for (int i = 0; i < 10; i++)
{
   sum = sum + (Integer) numbers.get(i);
}
Ob'ektlar kolleksiyasini yaratish, Object turiga ishorat saqlash

Kolleksiyani raqamlar bilan to'ldirish: 10, 20, ... 100;



Kolleksiya elementlarini jamlash


Turini o'zgartirish zarur

Kammentariy 2.

Ma'lum turdagi elementlar kolleksiyada saqlanishiga hech qanday kafolat yo'q edi

Kod Izoh
ArrayList numbers = new ArrayList();


for (int i = 0; i < 10; i++)
   numbers.add(i * 2.5);


int sum = 0;
for (int i = 0; i < 10; i++)
{
   sum = sum + (Integer) numbers.get(i);
}
Ob'ektlar kolleksiyasini yaratish uchun ishorat saqlash Object turiga

Kolleksiyani Double turdagi raqamlar bilan to'ldirish:
0.0, 2.5, 5.0, ...


Kolleksiya elementlarini jamlash


Xato bo'ladi: Double turini Integer turiga o'zgartirish imkonsiz

Ma'lumotlar kolleksiyani har qanday yerda to'ldirilishi mumkin:

  • boshqa metodda
  • boshqa dasturda
  • fayldan yuklash
  • tarmoqqa ulanish orqali olish

Kammentariy 3.

Kolleksiya ma'lumotlarini bilmasdan o'zgartirish mumkin.

Siz kolleksiyani, to'ldirilgan ma'lumotlarni qandaydir metodga uzatishingiz mumkin, va bu metod, boshqa dasturchi tomonidan yozilgan, sizning kolleksiyangizga o'zining ma'lumotlarini qo'shishi mumkin.

Kolleksiya nomidan qanday turdagi ma'lumotlar saqlanishi aniq emas. Hatto o'zgaruvchiga nom berilsa ham, unga ishorat bir nechta metodlarga uzatilib, bu metodlarda dastlabki o'zgaruvchi nomi haqida hech qanday ma'lumot bo'lmaydi.


3. Generics

Generics в Java

Barcha bu muammolarni Java-dagi ajoyib narsa — generics (Generics) tuzatadi.

Java da generics deganda turli kombinatsiyalarni turlarga-parametrlar qo'shish imkoniyati tushuniladi. Shu tarzda murakkab tuzilgan turlar hosil bo'ladi. Bunday tuzilgan tur umumiy holda quyida ko'rsatilgan:

AsosiyTur<TurParametr>

Hammasi birgalikda – bu aynan tur. Va u turlar qo'llanishi mumkin bo'lgan yerlarda ishlatilishi mumkin.

Kod Tavsif
ArrayList<Integer> list;
O'zgaruvchilar yaratish
list = new ArrayList<Integer> ();
Obyektlar yaratish
ArrayList<Integer>[] array;
Massivlar yaratish

Bunday kolleksiyaga faqat Integer turidagi o'zgaruvchilarni saqlash mumkin:

Kod Tavsif
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(new Integer(1));
list.add(2);
list.add("Привет");
ArrayList turidagi kolleksiya Integer elementlari bilan
Bu mumkin
Bu ham mumkin: ishlaydi
autoboxing

Bu mumkin emas: kompilyatsiya xatosi

O'z klasslaringizni tur-parametrlar bilan qanday yaratishni, siz Java Collections qismida o'zlashtirasiz. Hozir esa biz qanday foydalanishni va bu qanday ishlashini tushunamiz.


4. Generics qanday ishlaydi

Aslida Generics juda oddiy ishlaydi.

Kompilyator turga parametr qo'shilgan tur ni almashtirib qo'yadi, lekin parametr qo'shilmagan. Va uning metodlari bilan ishlashda tur-parametriga o'tishni qo'shadi:

Kod Kompilyator nima qiladi
ArrayList<Integer> list = new ArrayList<Integer>();
ArrayList list = new ArrayList();
list.add(1);
list.add( (Integer) 1 );
int x = list.get(0);
int x = (Integer) list.get(0);
list.set(0, 10);
list.set(0, (Integer) 10);

Faraz qilaylik, bizda butun sonlar kolleksiyasidagi sonlarni chiqaruvchi metod kodi bor:

Kod Kompilyator nima qiladi
public int sum(ArrayList<Integer> numbers)
{
   int result = 0;

   for (int i = 0; i < numbers.size(); i++)
      result = result + numbers.get(i);

   return result;
}
public int sum(ArrayList numbers)
{
   int result = 0;

   for (int i = 0; i < numbers.size(); i++)
      result = result + (Integer) numbers.get(i);

   return result;
}

Ya'ni, asosan generics bu - sintaksisli shakar turi, autoboxing kabi, faqat biroz ko'proq. Autoboxing bilan kompilyator biz uchun int turini Integer va orqaga o'zgartirish metodlarini qo'shadi, generics uchun esa turini o'zgartirish operatorlarini qo'shadi.

Kodning generics bilan kompilyatsiyalanganidan so'ng, unda parametrlar bo'lgan barcha classlar oddiy classlarga va turini o'zgartirish operatorlariga aylantirilgan. Murakkab turlardagi dastlabki parametr turlari haqidagi ma'lumotlar yo'qolgan. Bu effektni turlarini o'chirish ham deyiladi.

O'z klasslaringizni tur-parametrlar bilan yaratgan dasturchilar ba'zan, parametr sifatida qanday turlar kirib kelingani haqidagi ma'lumot yetarli emas. Bu muammoning yechimi va natijasi haqida siz Java Collections qismida bilib olasiz.



5. Generics haqida bir nechta faktlar

Generics haqida yana bir nechta qiziqarli faktlar.

Classlarda bitta emas, bir nechta tip parametr bo'lishi mumkin. Bu taxminan quyidagicha ko'rinadi:

AsosiyTur<TurParametr1, TurParametr2, TurParametr3>

Bu aslida hayratlanarli narsa emas. Kompilyator bitta turga o'tishni qo'shishi mumkin bo'lgan joyda, u bir nechta shunday o'tishlarni ham qo'sha olishi mumkin.

Misollar:

Kod Izoh
HashMap<Integer, String> map = new HashMap<Integer, String>();
map.put(7, "Привет");
map.put(-15, "Привет");
put metodining birinchi parametri Integer turiga, ikkinchisi — String turiga ega

Shuningdek murakkab turlar ham parametr sifatida foydalanish mumkin. Bu taxminan quyidagicha ko'rinadi:

AsosiyTur<TurParametr<TurParametrParametri>>

Faraz qilaylik, biz matnlar saqlanadigan ro'yxatni yaratmoqchimiz. Bunday holda biz taxminan quyidagi kodni hosil qilamiz:

// salomlashish ro'yxati
ArrayList<String> listHello = new ArrayList<String>();
listHello.add("Привет");
listHello.add("Hi");

// xayrlashish ro'yxati
ArrayList<String> listBye = new ArrayList<String>();
listBye.add("Пока");
listBye.add("Good Bye");

// ro'yxatlar ro'yxati
ArrayList<ArrayList<String>> lists = new ArrayList<ArrayList<String>>();
lists.add(listHello);
lists.add(listBye);
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION