JavaRush /Java blogi /Random-UZ /Java dasturchisi uchun intervyudan olingan savollar va ja...

Java dasturchisi uchun intervyudan olingan savollar va javoblarni tahlil qilish. 15-qism

Guruhda nashr etilgan
Salom salom! Java dasturchisi qancha bilishi kerak? Siz bu masala bo'yicha uzoq vaqt bahslashishingiz mumkin, ammo haqiqat shundaki, suhbatda sizni nazariy jihatdan to'liq harakatga keltirasiz. Hatto o'sha bilim sohalarida ham o'z ishingizda foydalanish imkoniyati bo'lmaydi. Java dasturchisi uchun intervyudan olingan savollar va javoblarni tahlil qilish.  15-1-qismXo'sh, agar siz yangi boshlovchi bo'lsangiz, sizning nazariy bilimingiz juda jiddiy qabul qilinadi. Hozircha tajriba va katta yutuqlar yo'qligi sababli, bilim bazasining mustahkamligini tekshirish qoladi. Bugun biz Java dasturchilari uchun eng mashhur intervyu savollarini ko'rib chiqish orqali ushbu bazani mustahkamlashda davom etamiz. Keling, uchamiz!

Java yadrosi

9. Java-da statik va dinamik bog'lanish o'rtasidagi farq nima?

Men ushbu maqolada statik va dinamik polimorfizm haqida 18-savolda allaqachon javob berganman , uni o'qishni maslahat beraman.

10. Interfeysda shaxsiy yoki himoyalangan o'zgaruvchilardan foydalanish mumkinmi?

Mumkin emas. Chunki siz interfeysni e'lon qilganingizda, Java kompilyatori avtomatik ravishda interfeys usullaridan oldin ommaviy va mavhum kalit so'zlarni va ma'lumotlar a'zolaridan oldin umumiy , statik va yakuniy kalit so'zlarni qo'shadi. Aslida, agar siz private yoki protected ni qo'shsangiz , ziddiyat yuzaga keladi va kompilyator kirish modifikatoridan shikoyat qiladi: “Bu yerda '<tanlangan modifikator>' modifikatoriga ruxsat berilmaydi.” Nima uchun kompilyator umumiy , statik va finalni qo'shadi. interfeysdagi o'zgaruvchilar? Keling, buni aniqlaylik:
  • ommaviy - interfeys mijozga ob'ekt bilan o'zaro munosabatda bo'lish imkonini beradi. Agar o'zgaruvchilar ommaviy bo'lmasa, mijozlar ularga kirish huquqiga ega bo'lmaydi.
  • statik - interfeyslarni yaratib bo'lmaydi (aniqrog'i, ularning ob'ektlari), shuning uchun o'zgaruvchi statikdir.
  • final - interfeys 100% abstraktsiyaga erishish uchun ishlatilganligi sababli, o'zgaruvchining yakuniy shakli mavjud (va o'zgartirilmaydi).

11. Classloader nima va u nima uchun ishlatiladi?

Classloader - yoki Class Loader - Java sinflarini yuklashni ta'minlaydi. Aniqrog'i, yuklash uning avlodlari - o'ziga xos sinf yuklagichlari tomonidan ta'minlanadi, chunki ClassLoaderning o'zi mavhumdir. Har safar .class fayli yuklanganda, masalan, mos keladigan sinfning konstruktori yoki statik usulini chaqirgandan so'ng, bu harakat ClassLoader sinfining avlodlaridan biri tomonidan amalga oshiriladi . Vorislarning uch turi mavjud:
  1. Bootstrap ClassLoader JVM darajasida amalga oshirilgan asosiy yuklovchi bo'lib, ish vaqti muhitidan hech qanday fikr bildirmaydi, chunki u JVM yadrosining bir qismi bo'lib, mahalliy kodda yozilgan. Ushbu yuklovchi barcha boshqa ClassLoader misollarining ota-onasi bo'lib xizmat qiladi.

    Asosan JDK ichki sinflarini, odatda rt.jar va $JAVA_HOME/jre/lib katalogida joylashgan boshqa asosiy kutubxonalarni yuklash uchun javobgardir . Turli platformalarda ushbu sinf yuklagichining turli xil ilovalari bo'lishi mumkin.

  2. Extension Classloader - kengaytmali yuklovchi, asosiy yuklovchi sinfining avlodi. Standart Java tayanch sinflarining kengaytmasini yuklash haqida g'amxo'rlik qiladi. JDK kengaytmalari katalogidan yuklanadi, odatda $JAVA_HOME/lib/ext yoki java.ext.dirs tizimi xususiyatida qayd etilgan boshqa har qanday katalog (bu parametr kengaytmalarni yuklashni boshqarish uchun ishlatilishi mumkin).

  3. System ClassLoader JVM ga barcha amaliy darajadagi sinflarni yuklash bilan shug'ullanadigan JRE darajasida amalga oshirilgan tizim yuklagichidir. U sinf muhiti o'zgaruvchisi -classpath yoki -cp buyruq qatorida topilgan fayllarni yuklaydi.

Java dasturchisi uchun intervyudan olingan savollar va javoblarni tahlil qilish.  15-2-qismSinf yuklagichlari Java ish vaqtining bir qismidir. JVM sinfni so'ragan paytda, sinf yuklovchisi sinfni topishga va sinfning to'liq malakali nomidan foydalanib sinf ta'rifini ish vaqtiga yuklashga harakat qiladi. Java.lang.ClassLoader.loadClass() usuli ish vaqtida sinf ta'rifini yuklash uchun javobgardir. U sinfni toʻliq nomi asosida yuklashga harakat qiladi. Agar sinf hali yuklanmagan bo'lsa, u so'rovni asosiy sinf yuklovchisiga topshiradi. Bu jarayon rekursiv ravishda sodir bo'ladi va quyidagicha ko'rinadi:
  1. System Classloader o'z keshidagi sinfni topishga harakat qiladi.

    • 1.1. Agar sinf topilsa, yuklash muvaffaqiyatli yakunlandi.

    • 1.2. Agar sinf topilmasa, yuklash Extension Classloader-ga topshiriladi.

  2. Classloader kengaytmasi sinfni o'z keshida topishga harakat qiladi.

    • 2.1. Agar sinf topilsa, u muvaffaqiyatli yakunlanadi.

    • 2.2. Agar sinf topilmasa, yuklash Bootstrap Classloader-ga topshiriladi.

  3. Bootstrap Classloader sinfni o'z keshida topishga harakat qiladi.

    • 3.1. Agar sinf topilsa, yuklash muvaffaqiyatli yakunlandi.

    • 3.2. Agar sinf topilmasa, asosiy Bootstrap Classloader uni yuklashga harakat qiladi.

  4. Agar yuklansa:

    • 4.1. Muvaffaqiyatli - sinfni yuklash tugallandi.

    • 4.2. Muvaffaqiyatsiz bo'lsa, boshqaruv Kengaytma Classloader-ga o'tkaziladi.

  5. 5. Extension Classloader sinfni yuklashga harakat qiladi va agar yuklansa:

    • 5.1. Muvaffaqiyatli - sinfni yuklash tugallandi.

    • 5.2. Agar u bajarilmasa, boshqaruv tizim Classloader-ga o'tkaziladi.

  6. 6. System Classloader sinfni yuklashga harakat qiladi va agar yuklansa:

    • 6.1. Muvaffaqiyatli - sinfni yuklash tugallandi.

    • 6.2. Muvaffaqiyatli o'tmadi - istisno yaratildi - ClassNotFoundException.

Sinf yuklagichlari mavzusi juda katta va uni e'tiborsiz qoldirmaslik kerak. U bilan batafsilroq tanishish uchun men sizga ushbu maqolani o'qishni maslahat beraman , va biz davom etmaymiz va davom etmaymiz.

12. Run-time ma'lumotlar zonalari nima?

Run-Time Data Ares - JVM ish vaqti ma'lumotlar maydonlari. JVM dasturni bajarish paytida zarur bo'lgan ba'zi ish vaqti ma'lumotlar maydonlarini belgilaydi. Ulardan ba'zilari JVM ishga tushganda yaratiladi. Boshqalar ip-lokal bo'lib, faqat ip yaratilganda yaratiladi (va ip yo'q qilinganda yo'q qilinadi). JVM ish vaqti ma'lumotlar maydonlari quyidagicha ko'rinadi: Java dasturchisi uchun intervyudan olingan savollar va javoblarni tahlil qilish.  15-3-qism
  • Kompyuter registri har bir ish zarrachasi uchun mahalliy bo'lib, u hozirda bajarilayotgan JVM yo'riqnomasining manzilini o'z ichiga oladi.

  • JVM Stack - bu mahalliy o'zgaruvchilar va vaqtinchalik natijalar uchun saqlash sifatida ishlatiladigan xotira maydoni. Har bir ip o'zining alohida stekiga ega: ip tugashi bilan bu stek ham yo'q qilinadi. Shuni ta'kidlash kerakki, stekning to'pdan ustunligi unumdorlikdir, shu bilan birga yig'ishning saqlash miqyosida afzalligi bor.

  • Native Method Stack - Mahalliy (Java bo'lmagan) usullarni bajarish uchun JVM stekiga o'xshash ma'lumotlar elementlarini saqlaydigan har bir mavzu bo'yicha ma'lumotlar maydoni.

  • Uyma - barcha ish zarralari tomonidan ish vaqtida yaratilgan ob'ektlar, sinf metama'lumotlari, massivlar va boshqalarni o'z ichiga olgan do'kon sifatida ishlatiladi. Bu maydon JVM ishga tushirilganda yaratiladi va u yopilganda yo'q qilinadi.

  • Usul maydoni - Bu ish vaqti maydoni barcha oqimlar uchun umumiy bo'lib, JVM ishga tushirilganda yaratiladi. U har bir sinf uchun tuzilmalarni saqlaydi, masalan, Runtime Constant Pool, konstruktorlar va usullar uchun kodlar, metod ma'lumotlari va boshqalar.

13. O'zgarmas ob'ekt nima?

Maqolaning ushbu qismida , 14 va 15-savollarda bu savolga allaqachon javob bor, shuning uchun vaqtingizni behuda sarflamasdan ko'rib chiqing.

14. String sinfining o'ziga xos xususiyati nimada?

Ilgari tahlilda biz Stringning ma'lum xususiyatlari haqida bir necha bor gapirgan edik (buning uchun alohida bo'lim mavjud edi). Endi String ning xususiyatlarini umumlashtiramiz :
  1. Bu Java-dagi eng mashhur ob'ekt bo'lib, turli maqsadlarda qo'llaniladi. Foydalanish chastotasi bo'yicha u hatto ibtidoiy turlardan ham kam emas.

  2. Ushbu sinf ob'ekti new kalit so'zidan foydalanmasdan yaratilishi mumkin - to'g'ridan-to'g'ri tirnoqlar orqali String str = "string"; .

  3. String o'zgarmas sinfdir : bu sinf ob'ektini yaratishda uning ma'lumotlarini o'zgartirib bo'lmaydi (ma'lum bir satrga + "boshqa string" qo'shsangiz, natijada siz yangi, uchinchi qatorga ega bo'lasiz). String sinfining o'zgarmasligi uni ipni xavfsiz qiladi.

  4. String sinfi yakunlandi ( yakuniy modifikatorga ega ), shuning uchun uni meros qilib bo'lmaydi.

  5. String o'z satrli puliga ega , u yaratgan satr qiymatlarini keshlaydigan yig'ma xotira maydoni. Seriyaning ushbu qismida 62-savolda men simli hovuzni tasvirlab berdim.

  6. Java-da String ning o'xshashlari mavjud , shuningdek, strings bilan ishlash uchun mo'ljallangan - StringBuilder va StringBuffer , lekin ular o'zgaruvchanligi bilan farq qiladi. Ular haqida ko'proq ma'lumotni ushbu maqolada o'qishingiz mumkin .

Java dasturchisi uchun intervyudan olingan savollar va javoblarni tahlil qilish.  15-4-qism

15. Tur kovariatsiyasi nima?

Kovariatsiyani tushunish uchun biz bir misolni ko'rib chiqamiz. Aytaylik, bizda hayvonlar sinfi bor:
public class Animal {
 void voice() {
   System.out.println("*тишина*");
 }
}
Va ba'zi itlar sinfi uni kengaytiradi :
public class Dog extends Animal {

 @Override
 public void voice() {
   System.out.println("Гав, гав, гав!!!");
 }
}
Esda tutganimizdek, biz merosxo'r turdagi ob'ektlarni ota-ona turiga osongina belgilashimiz mumkin:
Animal animal = new Dog();
Bu polimorfizmdan boshqa narsa bo'lmaydi. Qulay, moslashuvchan, shunday emasmi? Xo'sh, hayvonlar ro'yxati haqida nima deyish mumkin? Umumiy Hayvonlar ro'yxatini Dog ob'ektlari bilan ro'yxatini bera olamizmi ?
List<Dog> dogs = new ArrayList<>();
List<Animal> animals = dogs;
Bunday holda, itlar ro'yxatini hayvonlar ro'yxatiga belgilash chizig'i qizil rang bilan chiziladi, ya'ni. kompilyator bu kodni o'tkaza olmaydi. Bu topshiriq juda mantiqiy tuyulganiga qaramay (axir biz Dog ob'ektini Animal tipidagi o'zgaruvchiga belgilashimiz mumkin ), buni amalga oshirib bo'lmaydi. Buning sababi, agar ruxsat berilsa, biz Hayvonlar ob'ektini dastlab It bo'lishi uchun mo'ljallangan ro'yxatga qo'yishimiz mumkin bo'lardi , lekin bizda faqat itlar ro'yxati bor deb o'ylaymiz . Va keyin, masalan, itlar ro'yxatidan ob'ektni olish uchun get() usulidan foydalanamiz , uni it deb o'ylaymiz va " Dog" ob'ektining Hayvonda yo'q qandaydir usulini chaqiramiz . Va tushunganingizdek, bu mumkin emas - xatolik yuz beradi. Ammo, xayriyatki, kompilyator ota-onalar ro'yxatiga avlodlar ro'yxatini belgilashda (va aksincha) bu mantiqiy xatoni o'tkazib yubormaydi. Java'da siz faqat ro'yxat ob'ektlarini mos keladigan generiklar bilan o'zgaruvchilar ro'yxatiga belgilashingiz mumkin. Bu invariatsiya deb ataladi. Agar ular buni qila olsalar, u kovariatsiya deb ataladi. Ya'ni, biz ArrayList<Dog> tipidagi ob'ektni List<Animal> tipidagi o'zgaruvchiga o'rnatishimiz mumkin bo'lsa, kovariatsiya hisoblanadi . Ma'lum bo'lishicha, Java-da kovariatsiya qo'llab-quvvatlanmaydi? Qanday bo'lmasin! Ammo bu o'ziga xos tarzda amalga oshiriladi. Dizayn nima uchun ishlatiladi ? Hayvonni kengaytiradi . U biz ro'yxat ob'ektini o'rnatmoqchi bo'lgan o'zgaruvchining generic bilan, avlodning umumiy bilan joylashtiriladi. Ushbu umumiy konstruktsiya Hayvon turining avlodi bo'lgan har qanday tur amalga oshirishini anglatadi (va hayvon turi ham ushbu umumlashtirishga kiradi). O'z navbatida, Animal nafaqat sinf, balki interfeys ham bo'lishi mumkin ( extens kalit so'ziga aldanmang ). Oldingi topshiriqni quyidagicha bajarishimiz mumkin: Java dasturchisi uchun intervyudan olingan savollar va javoblarni tahlil qilish.  15-5-qism
List<Dog> dogs = new ArrayList<>();
List<? extends Animal> animals = dogs;
Natijada, siz IDEda kompilyator ushbu konstruktsiyadan shikoyat qilmasligini ko'rasiz. Keling, ushbu dizaynning funksionalligini tekshiramiz. Aytaylik, bizda unga o'tgan barcha hayvonlarning tovush chiqarishiga sabab bo'ladigan usul bor:
public static void animalsVoice(List<? extends Animal> animals) {
 for (Animal animal : animals) {
   animal.voice();
 }
}
Keling, unga itlar ro'yxatini beraylik:
List<Dog> dogs = new ArrayList<>();
dogs.add(new Dog());
dogs.add(new Dog());
dogs.add(new Dog());
animalsVoice(dogs);
Konsolda biz quyidagi chiqishni ko'ramiz:
Voy vay voy!!! Voy vay voy!!! Voy vay voy!!!
Bu shuni anglatadiki, kovariatsiyaga bunday yondashuv muvaffaqiyatli ishlaydi. Shuni ta'kidlash kerakki, ushbu umumiy ro'yxatga kiritilganmi ? kengaytirilgan Animal biz har qanday turdagi yangi ma'lumotlarni kirita olmaymiz: na It turi , na hayvon turi :
List<Dog> dogs = new ArrayList<>();
List<? extends Animal> animals = dogs;
animals.add(new Dog());
dogs.add(new Animal());
Aslida, oxirgi ikki qatorda kompilyator ob'ektlarni qizil rang bilan kiritishni ta'kidlaydi. Buning sababi shundaki, biz umumiy <? kengaytiradi Animal> . Men kontravariatsiyaJava dasturchisi uchun intervyudan olingan savollar va javoblarni tahlil qilish.  15-6-qism haqida ham gapirishni istardim , chunki odatda bu tushuncha har doim kovariatsiya bilan birga keladi va qoida tariqasida ular haqida birgalikda so'raladi. Bu kontseptsiya kovariatsiyaga biroz qarama-qarshidir, chunki bu konstruktsiya merosxo'r turidan foydalanadi. Aytaylik, biz Dog ob'ektining ajdodi bo'lmagan turdagi ob'ektlar ro'yxati tayinlanishi mumkin bo'lgan ro'yxatni xohlaymiz . Biroq, ularning qanday aniq turlari bo'lishini oldindan bilmaymiz. Bunday holda, shaklning qurilishi ? super it , uning barcha turlari mos keladi - it sinfining avlodlari :
List<Animal> animals = new ArrayList<>();
List<? super Dog> dogs = animals;
dogs.add(new Dog());
dogs.add(new Dog());
Biz bunday umumiy ro'yxatga Dog tipidagi ob'ektlarni xavfsiz qo'shishimiz mumkin , chunki har qanday holatda ham u o'z ota-bobolarining barcha amalga oshirilgan usullariga ega. Ammo biz hayvon turidagi ob'ektni qo'sha olmaymiz , chunki ichkarida bunday turdagi ob'ektlar bo'lishiga ishonch yo'q, masalan, It emas . Oxir oqibat, biz ushbu ro'yxatning elementidan Animalda bo'lmaydigan Dog sinfining usulini so'rashimiz mumkin . Bunday holda, kompilyatsiya xatosi yuzaga keladi. Bundan tashqari, agar biz avvalgi usulni amalga oshirmoqchi bo'lsak, lekin bu umumiy bilan:
public static void animalsVoice(List<? super Dog> dogs) {
 for (Dog dog : dogs) {
   dog.voice();
 }
}
for loopida kompilyatsiya xatosiga duch kelamiz , chunki qaytarilgan ro'yxatda Dog tipidagi ob'ektlar borligiga ishonchimiz komil emas va uning usullaridan foydalanish bepul. Agar biz ushbu ro'yxatdagi dogs.get(0) usulini chaqirsak . - Object tipidagi ob'ektni olamiz . Ya'ni, animalVoice() usuli ishlashi uchun biz hech bo'lmaganda turdagi ma'lumotlarni toraytirgan holda kichik manipulyatsiyalarni qo'shishimiz kerak:
public static void animalsVoice(List<? super Dog> dogs) {
 for (Object obj : dogs) {
   if (obj instanceof Dog) {
     Dog dog = (Dog) obj;
     dog.voice();
   }
 }
}
Java dasturchisi uchun intervyudan olingan savollar va javoblarni tahlil qilish.  15-7-qism

16. Object sinfida qanday usullar mavjud?

Seriyaning ushbu qismida , 11-bandda men bu savolga allaqachon javob berganman, shuning uchun agar siz hali buni qilmagan bo'lsangiz, uni o'qishni maslahat beraman. Shu bilan bugungi kunimizni tugatamiz. Keyingi qismda ko'rishguncha! Java dasturchisi uchun intervyudan olingan savollar va javoblarni tahlil qilish.  15-8-qism
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION