Java sintaksisi biz yangi umumiy massiv yaratishimiz mumkinligini ko'rsatadi
Download 18.27 Kb.
|
tarmoq dasturlash mavzu No12
Mavzu: Umumiy ma’lumotlar tuzilmalarini (massivlar, ro‘yxatlar, daraxtlar va boshqalar) yaratish uchun sinf shablonlaridan foydalanish. 1.Kirish
Ushbu qo'llanmada biz generiklarni massivlar bilan ishlatishdagi qiyinchiliklarni muhokama qilamiz. Keyin biz umumiy massivning namunasini yaratamiz. Va nihoyat, Java API shunga o'xshash muammoni qanday hal qilganini ko'rib chiqamiz. 2. Umumiy massivlardan foydalanishda e'tiborga olish Massivlar va generiklar o'rtasidagi muhim farq ularning turini tekshirishni qanday amalga oshirishidir. Xususan, massivlar ish vaqtida turdagi ma'lumotlarni saqlaydi va tekshiradi. Biroq, generiklar kompilyatsiya vaqtida turdagi xatolarni tekshiradi va ish vaqtida turdagi ma'lumotlarga ega emas. Java sintaksisi biz yangi umumiy massiv yaratishimiz mumkinligini ko'rsatadi: T[] elements = new T[size]; Ammo agar biz buni sinab ko'rsak, kompilyatsiya xatosiga duch kelamiz. Buning sababini tushunish uchun keling, quyidagilarni ko'rib chiqaylik: public T[] genericArray = new T[size]; // suppose this is allowed return genericArray; } Bog'lanmagan umumiy T turi Ob'ektga echilganligi sababli , bizning ish vaqtidagi usulimiz quyidagicha bo'ladi: public Object[] getArray(int size) { Object[] genericArray = new Object[size]; return genericArray; }Nusxalash Agar biz usulimizni chaqirsak va natijani String massivida saqlasak: String[] myArray = getArray(5);Nusxalash Kod yaxshi kompilyatsiya qilinadi, lekin ClassCastException bilan ish vaqtida muvaffaqiyatsiz bo'ladi . Buning sababi, biz hozirgina Object[] ni String[] havolasiga tayinladik . Xususan, kompilyator tomonidan yashirin translatsiya Object[] ni bizning talab qilingan String[] turiga aylantira olmaydi . Umumiy massivlarni to'g'ridan-to'g'ri ishga tushira olmasak ham, agar ma'lumotning aniq turi qo'ng'iroq kodi bilan ta'minlangan bo'lsa, ekvivalent operatsiyaga erishish mumkin. 3. Umumiy massivni yaratish Misol uchun, sig'imi ma'lum bir o'lchamga o'rnatiladigan MyStack cheklangan stek ma'lumotlar strukturasini ko'rib chiqaylik. Biz stekning har qanday tur bilan ishlashini xohlayotganimiz sababli, oqilona amalga oshirish tanlovi umumiy massiv bo'ladi. Birinchidan, biz E tipidagi umumiy massiv bo'lgan stekimiz elementlarini saqlash uchun maydon yaratamiz : private E[] elements;Nusxalash Keyin biz konstruktorni qo'shamiz: public MyStack(Class elements = (E[]) Array.newInstance(clazz, capacity); }Nusxalash Ikki parametr talab qiladigan umumiy massivimizni ishga tushirish uchun java.lang.reflect.Array#newInstance dan qanday foydalanishimizga e'tibor bering. Birinchi parametr yangi massiv ichidagi ob'ekt turini belgilaydi. Ikkinchi parametr massiv uchun qancha joy yaratish kerakligini belgilaydi. Array#newInstance ning natijasi Object tipidagi bo‘lgani uchun umumiy massivimizni yaratish uchun uni E[] ga o‘tkazishimiz kerak . Bundan tashqari , Java-da ajratilgan so'z bo'lgan sinf emas , balki tip parametrlarini clazz deb nomlash konventsiyasiga e'tibor qaratishimiz kerak . 4. ArrayList ni ko'rib chiqish 4.1. Massiv o'rnida ArrayList dan foydalanish Ko'pincha umumiy massiv o'rniga umumiy ArrayList dan foydalanish osonroq . Keling, MyStack-ni ArrayList- dan foydalanish uchun qanday o'zgartirishimiz mumkinligini ko'rib chiqaylik . Birinchidan, biz elementlarimizni saqlash uchun maydon yaratamiz: private List Keyin, stek konstruktorimizda biz ArrayList- ni boshlang'ich sig'im bilan ishga tushirishimiz mumkin: elements = new ArrayList<>(capacity);Nusxalash Bu bizning sinfimizni soddalashtiradi, chunki biz aks ettirishdan foydalanishimiz shart emas. Bundan tashqari, stekni yaratishda bizdan sinf literaliga o'tishimiz shart emas. ArrayList ning boshlang'ich sig'imini o'rnatishimiz mumkin bo'lsa , biz massiv bilan bir xil foyda olishimiz mumkin. Shuning uchun, biz kamdan-kam hollarda yoki massivni talab qiladigan ba'zi tashqi kutubxonalar bilan bog'langanimizda generiklar massivlarini yaratishimiz kerak. 4.2. ArrayListni amalga oshirish Qizig'i shundaki, ArrayListning o'zi umumiy massivlar yordamida amalga oshiriladi. Keling, qanday qilib ArrayList ichiga nazar tashlaylik. Birinchidan, ro'yxat elementlari maydonini ko'rib chiqamiz: transient Object[] elementData; Eslatma ArrayList element turi sifatida Ob'ektdan foydalanadi . Bizning umumiy turimiz ish vaqtigacha noma'lum bo'lgani uchun Ob'ekt har qanday turdagi supersinf sifatida ishlatiladi. Shuni ta'kidlash kerakki, ArrayList -dagi deyarli barcha amallar ushbu umumiy massivdan foydalanishi mumkin, chunki ular tashqi dunyoga qattiq terilgan massivni taqdim etishi shart emas (bir usuldan tashqari, toArray). 5. To‘plamdan massiv qurish 5.1. LinkedList misoli Keling, Java Collections API-da umumiy massivlardan foydalanishni ko'rib chiqaylik, bu erda biz to'plamdan yangi massiv tuzamiz. Birinchidan, biz String argumentli yangi LinkedList yaratamiz va unga elementlar qo'shamiz: List items.add("first item"); items.add("second item"); Nusxalash Keyin biz qo'shgan narsalar qatorini tuzamiz: String[] itemsAsArray = items.toArray(new String[0]);Nusxalash Bizning massivimizni yaratish uchun, List . toArray usuli kirish massivini talab qiladi. U ushbu massivdan faqat to'g'ri turdagi qaytish massivini yaratish uchun turdagi ma'lumotlarni olish uchun foydalanadi. Yuqoridagi misolimizda biz yangi String[0] dan olingan qatorni yaratish uchun kirish massivi sifatida foydalandik . 5.2. LinkedList.toArray amalga oshirish Keling, Java JDK da qanday amalga oshirilganligini ko'rish uchun LinkedList.toArray ichiga nazar tashlaylik. Birinchidan, biz usul imzosini ko'rib chiqamiz: public Keyin kerak bo'lganda yangi massiv qanday yaratilishini ko'rib chiqamiz: a = (T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);Nusxalash Oldingi stek misolimizdagi kabi yangi massivni yaratish uchun Array#newInstance dan qanday foydalanishiga e'tibor bering . Bundan tashqari, a parametri Array#newInstance turini taqdim etish uchun ishlatilishini ko'rishimiz mumkin . Nihoyat, umumiy massivni yaratish uchun Array#newInstance natijasi T[] ga uzatiladi . 6. Oqimlardan massivlar yaratish Java Streams API bizga oqimdagi elementlardan massivlar yaratish imkonini beradi. To'g'ri turdagi massivni ishlab chiqarishimizga ishonch hosil qilish uchun bir nechta tuzoqlarga e'tibor berish kerak. 6.1. toArray dan foydalanish Biz elementlarni Java 8 Stream- dan massivga osongina o'zgartirishimiz mumkin: Object[] strings = Stream.of("A", "AAA", "B", "AAB", "C") .filter(string -> string.startsWith("A")) .toArray(); assertThat(strings).containsExactly("A", "AAA", "AAB"); Nusxalash Ammo shuni ta'kidlash kerakki, asosiy toArray funktsiyasi bizga String massivini emas, balki Object massivini taqdim etadi : assertThat(strings).isNotInstanceOf(String[].class);Nusxalash Yuqorida aytib o'tganimizdek, har bir massivning aniq turi boshqacha. Oqimdagi tur generik bo'lgani uchun kutubxonaning ish vaqtida turini aniqlashning imkoni yo'q . 6.2. Yozilgan massivni olish uchun toArray ortiqcha yukidan foydalanish Umumiy yig'ish sinfi usullari ma'lum turdagi massivni yaratish uchun aks ettirishdan foydalansa, Java Streams kutubxonasi funktsional yondashuvdan foydalanadi. Stream uni toʻldirishga tayyor boʻlganda , toʻgʻri oʻlcham va turdagi massivni yaratadigan lambda yoki usul maʼlumotnomasida oʻtishimiz mumkin : String[] strings = Stream.of("A", "AAA", "B", "AAB", "C") .filter(string -> string.startsWith("A")) .toArray(String[]::new); assertThat(strings).containsExactly("A", "AAA", "AAB"); assertThat(strings).isInstanceOf(String[].class);Nusxalash Biz o'tkazadigan usul IntFunction bo'lib , u butun sonni kirish sifatida qabul qiladi va shu o'lchamdagi yangi massivni qaytaradi. String[] konstruktori aynan shunday qiladi, shuning uchun biz String[]::new usulidan foydalanishimiz mumkin . 6.3. O'z turi parametri bilan generiklar Tasavvur qilaylik, biz oqimimizdagi qiymatlarni o'zi turdagi parametrga ega bo'lgan ob'ektga aylantirmoqchimiz, masalan, List yoki Optional . Ehtimol, bizda qo'ng'iroq qilmoqchi bo'lgan API mavjud bo'lib, u Optional Ushbu turdagi massivni e'lon qilish to'g'ri: Optional Shuningdek, xarita usuli yordamida Stream Stream .filter(string -> string.startsWith("A")) .map(Optional::of);Nusxalash Biroq, agar biz massivni qurishga harakat qilsak, yana kompilyator xatosiga duch kelamiz: // compiler error Optional Yaxshiyamki, bu misol bilan oldingi misollarimiz o'rtasida farq bor. String[] Object[] ning quyi sinfi bo'lmasa , Optional [] aslida Optional Stream .filter(string -> string.startsWith("A")) .map(Optional::of); Optional .toArray(Optional[]::new);Nusxalash Bu kod kompilyatsiya qiladi va ishlaydi, lekin bizga belgilanmagan topshiriq haqida ogohlantirish beradi. Buni tuzatish uchun usulimizga SuppressWarnings qo'shishimiz kerak : @SuppressWarnings("unchecked")Nusxalash 6.4. Yordamchi funksiyadan foydalanish Agar biz kodimizning bir nechta joylariga SuppressWarnings ni qo'shmaslikni istasak va umumiy massivning xom turdagi yaratilishini hujjatlashtirishni istasak, yordamchi funktsiyani yozishimiz mumkin: @SuppressWarnings("unchecked") static return size -> (R[]) arrayCreator.apply(size); }Nusxalash Ushbu funktsiya xom turdagi massivni bizga kerak bo'lgan aniq turdagi massivni yaratishni va'da qiladigan funktsiyaga aylantiradi: Optional .filter(string -> string.startsWith("A")) .map(Optional::of) .toArray(genericArray(Optional[]::new));Nusxalash Belgilanmagan topshiriq haqidagi ogohlantirishni bu erda bostirish shart emas. Ammo shuni ta'kidlash kerakki, bu funktsiyani yuqori turlarga translyatsiya qilish uchun chaqirish mumkin. Misol uchun, agar bizning oqimimizda List ArrayList .toArray(genericArray(List[]::new));Nusxalash Bu kompilyatsiya qilinadi, lekin ArrayList[] List[] ning pastki sinfi emasligi sababli ClassCastExceptionni chiqaradi . Kompilyator buning uchun tekshirilmagan topshiriq ogohlantirishini ishlab chiqaradi, shuning uchun uni aniqlash oson. Download 18.27 Kb. Do'stlaringiz bilan baham: |
Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©fayllar.org 2024
ma'muriyatiga murojaat qiling
ma'muriyatiga murojaat qiling