Barcha savollar

Java bo'yicha eng muhim 100 ta intervyu savoli: suhbatdan muvaffaqiyatli o'ting

Java intervyu savollarining ushbu mukammal ro'yxati bilan suhbatdan muvaffaqiyatli o'ting — u sizga aqlliroq va tezroq tayyorlanishga yordam berish uchun tuzilgan.

Muallif: Fernando Doglio

Yaqinlashib kelayotgan Java intervyusiga tayyorlanmoqchimisiz? Yoki iste'dodli mutaxassislarni topish uchun mukammal savollar to'plamini tuzmoqchi bo'lgan hiring manager'misiz? Qanday bo'lmasin, ushbu maqola Java intervyu savollari bo'yicha sizning asosiy manbangizga aylanadi.

Java o'nlab yillar davomida asosiy texnologiyalardan biri bo'lib kelmoqda va enterprise ilovalardan tortib mobil ilovalargacha hamma narsani harakatga keltiradi. Uning uzoq yillik mashhurligi shuni anglatadiki, Java Virtual Machine (JVM)'dan tortib ilg'or object-oriented programming tushunchalarigacha bo'lgan nozik jihatlarini puxta tushunish juda muhim.

Tayyorlanishingizga yordam berish uchun tajriba darajasi bo'yicha puxta saralangan savollarning keng ro'yxatini tuzdik. Biroq, agar sizga batafsilroq roadmap kerak bo'lsa, boshlang'ich darajadan professional darajagacha kerak bo'ladigan hamma narsani o'z ichiga olgan ushbu JAVA developer roadmap'ni ko'rib chiqishingiz mumkin.

Xo'sh, keling, Java sirlarini ochishga va navbatdagi suhbatdan muvaffaqiyatli o'tishga tayyorlanaylik!

Navbatdagi intervyuga tayyorgarlik

Lekin savollar ro'yxatiga o'tishdan oldin shuni aytish kerakki, Java intervyusiga tayyorgarlik shunchaki javoblarni yodlashdan iborat emas. Gap tushunchangizni, muammolarni hal qilish ko'nikmalaringizni va dasturlashga bo'lgan ishtiyoqingizni namoyish etishda.

  • "Nima uchun"ni tushuning: Shunchaki ta'riflarni takrorlamang. Masalan, sizdan class method'lar haqida so'rashsa, nima uchun ulardan birini ishlatishingizni tushuntiring. Tushunchalarning amaliy qo'llanilishini anglaganingizni ko'rsating.

  • Kod yozishni mashq qiling: Ko'plab intervyularda live coding topshiriqlari bo'ladi. Toza, samarali va yaxshi izohlangan kod yozishni mashq qiling.

  • Savollar bering: Intervyu — ikki tomonlama jarayon. Lavozim, jamoa, kompaniya madaniyati va ularning development amaliyotlari haqida savollar tayyorlang. Bu sizning qiziqishingizni ko'rsatadi.

  • Asosiy tushunchalarni takrorlang: Hatto yuqori darajadagi lavozimga intervyu topshirayotgan bo'lsangiz ham, exception handling, multi-threading va garbage collection kabi core Java tushunchalari bo'yicha mustahkam poydevor zarur.

  • Ovoz chiqarib fikrlang: Sizga masala berilganda, fikrlash jarayoningizni ovoz chiqarib ayting. Dastlabki g'oyalaringizni, trade-off'larni va yechimga qanday kelganingizni tushuntiring. Bu intervyu oluvchiga muammolarni hal qilishga yondashuvingiz haqida tasavvur beradi.

  • Yangiliklardan xabardor bo'ling: Java doimiy rivojlanib bormoqda. Yangi versiyalarda kiritilgan so'nggi o'zgarishlar va imkoniyatlardan xabardor bo'ling. Bu doimiy o'rganishga sodiqligingizni ko'rsatadi.

Endi bu yerga kelganingiz sababiga o'taylik: quyida boshlovchilar, ilg'or darajadagi dasturchilar va tajribali professionallar uchun toifalarga ajratilgan 100 ta muhim Java intervyu savoli keltirilgan.

Flashcard'lar bilan o'zingizni sinab ko'ring

Siz ushbu flashcard'lardan foydalanishingiz yoki savollarni ro'yxat ko'rinishida ko'rish uchun quyidagi savollar ro'yxati bo'limiga o'tishingiz mumkin.

Savollar ro'yxati

Agar savollarni ro'yxat ko'rinishida ko'rishni afzal ko'rsangiz, ularni quyida topishingiz mumkin.

Boshlang'ich darajadagi Java intervyu savollari

Java nima? U boshqa dasturlash tillaridan nimasi bilan farq qiladi?

Java — dasturchini kodni bajaradigan hardware'ning murakkabliklaridan ataylab ajratib turadigan object-oriented programming (OOP) tili. Uning platformadan mustaqilligi ("Write Once, Run Anywhere") va kuchli xotira boshqaruvi (masalan, garbage collection) tilni boshqalardan eng ko'p ajratib turadigan ikki xususiyati bo'lib, uni yuqori darajada portable va mustahkam qiladi.

Java'dagi "Write Once, Run Anywhere" tushunchasini tushuntiring.

"Write Once, Run Anywhere" (WORA) shuni anglatadiki, bytecode'ga compile qilingan Java kodi Java Virtual Machine (JVM) o'rnatilgan har qanday platformada (operatsion tizim, hardware) kodga hech qanday maxsus o'zgartirish kiritmasdan ishlay oladi.

Java Virtual Machine (JVM) nima? Java dasturini ishga tushirishda uning roli qanday?

Oddiy qilib aytganda, JVM — sizning Java dasturlaringizni ishga tushiradigan narsa. Har bir tizim uchun (har bir OS, har bir hardware arxitekturasi va hokazo) bitta JVM bo'lishi orqali WORA tamoyiliga erishiladi (kodingizni bir marta yozasiz va uni ko'plab turli JVM'larda ishga tushirasiz).

Java Development Kit (JDK), Java Runtime Environment (JRE) va JVM o'rtasidagi farqni tushuntiring.

  • JDK (Java Development Kit): Java ilovalarini ishlab chiqish uchun ishlatiladigan software development muhiti. U JRE'ni (keyingi bandga qarang), shuningdek compiler va debugger kabi development vositalarini o'z ichiga oladi.

  • JRE (Java Runtime Environment): Java dasturini ishga tushirish uchun minimal talablarni ta'minlaydi. U JVM'ni (keyingi bandga qarang), asosiy sinflarni va yordamchi fayllarni o'z ichiga oladi.

  • JVM (Java Virtual Machine): Java bytecode'ni (dasturingizni) amalda bajaradigan dastur. U JRE'ning bir qismi.

Java'da primitive data type'lar qaysilar?

Sakkizta primitive data type mavjud: byte, short, int, long, float, double, boolean va char.

Java'da wrapper class'lar nima? Ular nima uchun ishlatiladi?

Wrapper class'lar primitive data type'lardan (masalan, int, char, boolean) obyekt sifatida foydalanish imkonini beradi. Ular primitive'larni Java Collections'da (ular faqat obyektlarni saqlaydi) saqlash hamda serialization kabi imkoniyatlarni qo'llab-quvvatlash uchun ishlatiladi.

Object-oriented programming (OOP) tushunchasini tushuntiring. Uning to'rtta asosiy tamoyili qaysilar?

Object-oriented programming (OOP) — "obyektlar" tushunchasiga asoslangan kod yozish usuli (programming paradigm); obyektlar ma'lumotlarni (ya'ni property'larni) va kodni (ya'ni method'lar yoki xatti-harakatni) o'z ichiga olishi mumkin. Uning to'rtta asosiy tamoyili: Encapsulation, Inheritance, Polymorphism va Abstraction.

Java'da sinf nima? U qanday e'lon qilinadi?

Sinfni obyektlar yaratish uchun mo'ljallangan chizma deb tasavvur qilishingiz mumkin (chizmani bir marta belgilaysiz va u yordamida ko'plab obyektlar yaratasiz). Uni class keyword'i, undan keyin sinf nomi, so'ngra uning a'zolarini (field'lar va method'larni) o'z ichiga olgan figurali qavslar yordamida e'lon qilasiz.

Misol: class Dog { /* ... */ }

Java'da obyekt nima?

"Chizma" o'xshatishini davom ettirsak, obyektni oldindan tayyorlangan chizma asosida qurilgan bino deb tasavvur qiling. Bitta chizma asosida ko'plab binolar qurishingiz mumkin bo'lganidek, bitta sinfdan ko'plab obyektlarni instantiate qilishingiz mumkin.

Java'da constructor nima? Sinfda bir nechta constructor bo'lishi mumkinmi?

Constructor — obyektlarni initialize qilish uchun ishlatiladigan maxsus method. Uning nomi sinf nomi bilan bir xil bo'ladi va return type'i bo'lmaydi. Ha, sinfda bir nechta constructor bo'lishi mumkin va bu "constructor overloading" deb ataladi.

Java'da new keyword'ining vazifasi nima?

new keyword'i sinfning instance'ini (obyektni) yaratish va unga heap'da xotira ajratish uchun ishlatiladi.

public static void main(String[] args) method'ini tushuntiring. Har bir keyword nima uchun muhim?

Bu har qanday Java dasturining entry point'i (Java dasturi ishga tushirilganda bu method avtomatik ravishda chaqiriladi). Butun signature qat'iy belgilangan.

  1. public: Access modifier; method'ni istalgan joydan foydalanish mumkin qiladi.

  2. static: Method'ni sinf obyektini yaratmasdan chaqirish imkonini beradi. U sinfning o'ziga tegishli bo'ladi.

  3. void: Method hech qanday qiymat qaytarmasligini bildiradi.

  4. main: JVM dasturning boshlanish nuqtasi sifatida taniydigan method'ning standart nomi.

  5. (String[] args): Command-line argumentlari uchun parametr — string'lar massivi.

Instance variable'lar va local variable'lar nima? Ular xotirada qayerda saqlanadi?

  • Instance variable'lar: Sinf ichida, lekin har qanday method, constructor yoki blokdan tashqarida e'lon qilinadi. Har bir obyektda ularning o'z nusxasi bo'ladi (ular obyektlar o'rtasida umumiy emas). Heap xotirada saqlanadi.

  • Local variable'lar: Method, constructor yoki blok ichida e'lon qilinadi. Ular faqat shu scope ichida mavjud bo'ladi. Stack xotirada saqlanadi.

Static variable'lar nima? Ular instance variable'lardan qanday farq qiladi?

Static variable'lar (shuningdek, class variable'lar deb ham ataladi) static keyword'i bilan e'lon qilinadi. Ular biror aniq obyekt instance'iga emas, balki sinfga tegishli bo'ladi. Sinfning barcha instance'lari static variable uchun bitta xotira manzilini baham ko'radi, instance variable esa har bir obyekt uchun alohida nusxaga ega bo'ladi.

Java'da static keyword'i nima uchun ishlatiladi? Static method'lar va static a'zolarni tushuntiring.

static keyword'i asosan xotirani boshqarish uchun ishlatiladi. U a'zoning (o'zgaruvchi yoki method) sinf instance'iga emas, balki sinfning o'ziga tegishli bo'lishiga imkon beradi.

  • Static method'lar: Obyekt yaratmasdan to'g'ridan-to'g'ri sinf orqali chaqirilishi mumkin (masalan, ClassName.staticMethod()). Ular instance method'larga kira olmaydi.

  • Static a'zolar: (O'zgaruvchilar yoki method'lar) sinf yuklanganda bir marta initialize qilinadi.

Method overloading nima? Misol keltiring.

Method overloading sinfga bitta sinf ichida bir xil nomli, lekin turli method signature'larga (parametrlar soni, type'i yoki tartibi turlicha) ega bir nechta method'ga ega bo'lish imkonini beradi.

Quyidagi misolda add method'i overload qilinadi:

class Calculator {
    int add(int a, int b) { return a + b; }
    double add(double a, double b) { return a + b; }
}

main method'ini overload qilish mumkinmi? Nima uchun?

Ha, main method'ini boshqa har qanday method kabi overload qilishingiz mumkin, lekin JVM dasturning entry point'i sifatida faqat public static void main(String[] args) signature'ini taniydi va bajaradi. Boshqa overload qilingan main method'larini kodingizdan to'g'ridan-to'g'ri chaqirishingiz kerak bo'ladi.

Method overriding nima? U overloading'dan qanday farq qiladi?

Method overriding child class o'zining parent class'ida allaqachon belgilangan method uchun yangi implementation taqdim etganda yuz beradi. Bu holda method'ning signature'i bir xil bo'lishi shart. U overloading'dan shunisi bilan farq qiladiki, overloading bitta sinf ichida turli signature'lar bilan sodir bo'ladi, overriding esa subclass'da bir xil signature bilan sodir bo'ladi.

Java'da inheritance nima? Misol bilan tushuntiring.

Inheritance — yangi sinf (child/subclass) mavjud sinfdan (parent/superclass) property'larni (field'lar va method'larni) meros qilib olishi mumkin bo'lgan OOP tamoyili. U kodni qayta ishlatishga yordam beradi.

Misol: class Dog extends Animal - Dog sinfi Animal sinfidan field'lar va method'larni meros qilib oladi.

Java'da interface nima? U abstract class'dan qanday farq qiladi?

Interface — sinfning chizmasi. U method signature'larini, default va private method'larni hamda static method'larni o'z ichiga olishi mumkin. U o'zini implement qiladigan sinflar uchun contract belgilaydi.

Abstract class'lardan farqlari: Interface'lar Java 8'dan beri rivojlanib keldi. Ilgari ular faqat abstract method'lar va konstantalar bilan cheklangan edi. Java 8 bilan static va default method'lar kiritildi, bu esa interface'ning o'zida method implementation'larini yozish imkonini berdi. Java 9'dan boshlab interface'dagi default va static method'lar o'rtasida kodni qayta ishlatishga yordam berish uchun private method'lar qo'shildi.

Abstract class'lar va abstract method'lar nima?

Abstract class'lar: Bular abstract keyword'i bilan e'lon qilingan sinflar. Ulardan to'g'ridan-to'g'ri instance yaratib bo'lmaydi va ular abstract hamda abstract bo'lmagan method'larni o'z ichiga olishi mumkin. Ular subclass'lar uchun asos bo'lishga mo'ljallangan (masalan, aslida Dogs yoki Cats obyektlarini yaratmoqchi bo'lganingizdagi Animal sinfi).

Abstract method'lar: Abstract class ichida abstract keyword'i bilan e'lon qilingan method'lar. Ularda method implementation bo'lmaydi va ular subclass'lar tomonidan implement qilinishi shart.

Encapsulation tushunchasini tushuntiring. Java'da unga qanday erishiladi?

Encapsulation sinfning attribute'larini va ular ustida ishlaydigan method'larni bir butunga birlashtiradi hamda ma'lumotlarning o'ziga to'g'ridan-to'g'ri kirishni cheklaydi. U obyektning ichki ishlashini yashirib, faqat public interface orqali o'zaro ishlash mumkin bo'lgan himoya qobig'ini ta'minlaydi.

Java'da bunga field'larga kirishni nazorat qilish uchun access modifier'lardan (private, public, protected, default) foydalanish va public getter hamda setter method'larini taqdim etish orqali erishishingiz mumkin.

Java'da polymorphism nima? Misol keltiring.

Polymorphism bitta interface'ni turli, o'zaro bog'liq sinflar uchun ishlatish imkonini beradi. Bu shuni anglatadiki, obyektga uning umumiy type'i sifatida munosabatda bo'lishingiz mumkin, garchi uning aniq xatti-harakati haqiqiy, asl sinfi bilan belgilansa ham. Bu bitta nom yoki method'ning bir nechta shaklga kira olish qobiliyatidir.

Misol: child class obyektiga murojaat qilish uchun parent class reference'idan foydalanish.

Animal myAnimal = new Dog(); // myAnimal can behave as an Animal or a Dog
myAnimal.makeSound(); // Calls Dog's makeSound() if overridden

Java'da package nima? Ular nima uchun ishlatiladi?

Package — o'zaro bog'liq sinflar va interface'larni tartibga solish usuli. Ular quyidagilar uchun ishlatiladi:

  • Modularity: O'zaro bog'liq type'larni guruhlash.

  • Nomlar to'qnashuvining oldini olish: Bir xil nomli sinflarning turli package'larda mavjud bo'lishiga imkon beradi.

  • Access control: Sinflar va a'zolarga kirishni nazorat qilish. (Maslahat: import java.* yoki import java.util.ArrayList;)

Java'da xatolar qanday qayta ishlanadi?

Java'da xatolar asosan try, catch, finally, throw va throws keyword'lari yordamida exception handling orqali qayta ishlanadi.

try-catch bloki nima? Uning vazifasini tushuntiring.

try-catch bloki exception handling uchun ishlatiladi. try bloki exception throw qilishi mumkin bo'lgan kodni o'z ichiga oladi. Agar exception yuz bersa, boshqaruv exception'ni qayta ishlaydigan catch blokiga o'tadi.

Exception handling'da finally bloki nima uchun ishlatiladi?

finally bloki try blokida exception yuz bergan yoki bermaganidan qat'i nazar, har doim bajariladigan kodni o'z ichiga oladi. U odatda resurslarni yopish kabi tozalash amallari uchun ishlatiladi.

throw va throws keyword'larining vazifasi nima?

  • throw: Method yoki kod blokidan exception'ni ochiq-oydin throw qilish uchun ishlatiladi.

  • throws: Method signature'ida method bir yoki bir nechta ko'rsatilgan type'dagi checked exception'larni throw qilishi mumkinligini e'lon qilish uchun ishlatiladi. U chaqiruvchiga bu exception'larni qayta ishlashi yoki e'lon qilishi kerakligini bildiradi.

Java'da final keyword'i nima? Final variable, final class va final method'ni tushuntiring.

final keyword'i entity'larni immutable qilish yoki o'zgartirish/inheritance'ning oldini olish uchun ishlatiladi.

  • final variable: Qiymati bir marta initialize qilingandan keyin o'zgartirib bo'lmaydigan o'zgaruvchi. U konstantaga aylanadi.

  • final class: Subclass yaratib (meros qilib olib) bo'lmaydigan sinf. Masalan, String sinfi.

  • final method: Subclass'lar tomonidan override qilib bo'lmaydigan method.

Java'da garbage collection nima? U qachon sodir bo'ladi?

Garbage collection — Java'dagi avtomatik jarayon bo'lib, u dasturning hech bir qismi endi reference qilmaydigan obyektlar egallagan xotirani qaytarib oladi. U JVM tomonidan xotira kamayib qolayotganini aniqlaganda yoki faollik past bo'lgan davrlarda avtomatik ravishda amalga oshiriladi.

Java'da == va .equals() o'rtasidagi farq nima?

  • ==: Reference'larni solishtirish uchun ishlatiladi (obyektlar uchun) — ikki reference bir xil xotira manziliga ishora qilishini tekshiradi. Primitive type'lar uchun u ularning qiymatlarini solishtiradi.

  • .equals(): Tarkibni solishtirish uchun ishlatiladigan method (obyektlar uchun) — ikki obyekt qiymatlariga ko'ra mantiqan "teng" ekanini tekshiradi. Uning xatti-harakatini sinflar override qilishi mumkin.

Java'da String sinfi nima? U mutable'mi yoki immutable'mi?

String sinfi character string'larni ifodalaydi. U immutable, ya'ni String obyekti yaratilgandan keyin uning tarkibini o'zgartirib bo'lmaydi. String'ni o'zgartirayotgandek ko'rinadigan har qanday amal aslida yangi String obyektini yaratadi.

Java'da string'lar qanday solishtiriladi?

Tarkibni solishtirish uchun odatda .equals() yoki .equalsIgnoreCase() method'laridan foydalanishingiz kerak.

StringBuffer va StringBuilder sinflari nima? Ular String'dan qanday farq qiladi?

StringBuffer ham, StringBuilder ham mutable belgilar ketma-ketligidir. Ular string tarkibini tez-tez o'zgartirish kerak bo'lganda ishlatiladi.

  • String: Immutable.

  • StringBuffer: Mutable va thread-safe (synchronized).

  • StringBuilder: Mutable va thread-safe emas (single-threaded muhitlar uchun tezroq).

Java'da massiv nima? Uni qanday e'lon qilasiz va initialize qilasiz?

Massiv — bitta type'dagi qat'iy sondagi qiymatlarni saqlaydigan container obyekt.

  • E'lon qilish: int[] numbers; yoki int numbers[];

  • Initialization: numbers = new int[5]; yoki int[] numbers = {1, 2, 3, 4, 5};

this keyword'ining vazifasi nima?

this keyword'i sinfning joriy instance'iga ishora qiladi. U quyidagilar uchun ishlatiladi:

  • Agar instance va local variable'lar bir xil nomga ega bo'lsa, ularni bir-biridan ajratish.

  • Bitta sinfdagi boshqa constructor'lar ichidan constructor'larni chaqirish.

super keyword'ining vazifasi nima?

super keyword'i joriy obyektning bevosita parent class'iga ishora qiladi. U quyidagilar uchun ishlatiladi:

  • Parent class method'lariga yoki constructor'lariga murojaat qilish.

  • Parent class'ning instance variable'lari subclass o'zgaruvchilari tomonidan yashirilganda ularga murojaat qilish.

Scanner sinfi nima uchun ishlatiladi?

Scanner class foydalanuvchi kiritgan ma'lumotlarni olish, primitive type'lar va string'larni regular expression'lar yordamida parse qilish uchun ishlatiladi. U java.util package'ining bir qismi.

Java'dagi null tushunchasini tushuntiring.

null — reference variable'larga (obyektlarga) berilishi mumkin bo'lgan maxsus literal. U o'zgaruvchi hech qanday obyektga ishora qilmasligini bildiradi. U qiymatning yo'qligini yoki mavjud bo'lmagan obyektni ifodalaydi.

Instance variable'lar va local variable'larga qanday default qiymatlar beriladi?

  • Instance variable'lar va static variable'lar ochiq-oydin initialize qilinmagan bo'lsa, ularga default qiymatlar beriladi: sonli type'lar (byte, short, int, long, float, double) uchun 0, char uchun \u0000 (null belgi), boolean uchun false va obyekt reference'lari uchun null.

  • Local variable'larga default qiymatlar berilmaydi va ular ishlatilishidan oldin ochiq-oydin initialize qilinishi shart; aks holda compile-time xatosi yuz beradi.

Ilg'or darajadagi Java intervyu savollari

Java Memory Model (JMM)'ni tushuntiring.

Java Memory Model (JMM) thread'lar xotira bilan qanday o'zaro ishlashini belgilaydi. U bir thread'ning amallari qanday sharoitlarda boshqalarga ko'rinishini aniqlab, thread'lar bo'ylab xotira amallarining izchilligi va tartibini (ordering) ta'minlaydi.

JVM xotirani qanday tashkil qiladi (Heap, Stack, Method Area)?

JVM xotirani bir nechta asosiy sohalarga ajratadi:

  • Heap Memory: Obyektlar va ularga tegishli instance variable'lar saqlanadigan joy. U barcha thread'lar o'rtasida umumiy bo'ladi.

  • Stack Memory: Har bir thread'ning o'z stack'i bo'ladi va unda local variable'lar hamda method chaqiruvlari frame'lari saqlanadi.

  • Method Area: Static variable'lar, method kodi va har bir yuklangan sinf uchun metadata kabi sinf darajasidagi ma'lumotlarni saqlaydi. String Pool ham shu yerda joylashadi.

Checked va unchecked exception'lar o'rtasidagi farq nima?

Checked exception'lar: Ushlanishi yoki method'ning throws qismida e'lon qilinishi shart bo'lgan exception'lar. Ular odatda yaxshi yozilgan ilova oldindan ko'zda tutishi va ulardan tiklanishi kerak bo'lgan tashqi muammolarni ifodalaydi (masalan, IOException).

Unchecked exception'lar: Ushlanishi yoki e'lon qilinishi shart bo'lmagan exception'lar. Ular odatda dasturlashdagi xatolarni bildiradi (masalan, NullPointerException, ArrayIndexOutOfBoundsException) va RuntimeException'ning subclass'lari hisoblanadi.

Java'dagi custom exception'lar haqida gapirib bering. Ularni qanday yaratasiz?

Custom exception'lar ilovangizdagi xatolik holatlari uchun o'zingizning maxsus exception type'laringizni belgilash imkonini beradi. Uni Exception'ni (checked exception uchun) yoki RuntimeException'ni (unchecked exception uchun) extend qilish orqali yaratasiz.

Misol:

class MyCustomException extends Exception {
    public MyCustomException(String message) {
        super(message);
    }
}

Java'dagi serialization va deserialization tushunchasini tushuntiring.

Serialization: Obyekt state'ini byte stream'ga aylantirish jarayoni; so'ngra uni faylga saqlash yoki tarmoq orqali uzatish mumkin.

Deserialization: Teskari jarayon — obyektni byte stream'dan qayta tiklash. Obyektlar java.io.Serializable interface'ini implement qilishi shart.

Java'da reflection nima? Undan qachon foydalanasiz?

Reflection — Java dasturining runtime'da o'z tuzilmasini (sinflar, method'lar, field'lar) tekshirish yoki o'zgartirish qobiliyati. Undan quyidagilar uchun foydalanasiz:

  • Obyektlarni dinamik yaratish va method'larni chaqirish uchun freymvorklar (masalan, Spring, Hibernate).

  • Debugging vositalari.

  • Testlash vositalari (masalan, mocking freymvorklari).

Java'da generics nima? Ular nima uchun foydali?

Generics sinflar, interface'lar va method'larni belgilashda type'larning (sinflar va interface'larning) parametr bo'lishiga imkon berib, type-safe dasturlashni ta'minlaydi. Ular foydali, chunki ular:

  • Type xatolarini runtime'da emas, compile time'da aniqlaydi.

  • Ochiq-oydin type casting zaruratini yo'qotadi.

  • Kodning o'qilishi va qayta ishlatilishini yaxshilaydi.

Java Collections Framework'ni tushuntiring. Ko'p ishlatiladigan ba'zi interface va sinflarni ayting.

Java Collections Framework — obyektlar to'plamlarini ifodalash va ular ustida amallar bajarish uchun yagona arxitekturani taqdim etadigan interface'lar va sinflar majmuasi. U List, Set, Map, Queue kabi interface'larni hamda ArrayList, HashSet, HashMap, LinkedList, TreeSet, TreeMap kabi sinflarni o'z ichiga oladi.

ArrayList va LinkedList o'rtasidagi farqni tushuntiring.

ArrayList: List interface'ini dynamic array yordamida implement qiladi. Tezkor random access uchun (elementni index bo'yicha olish) eng yaxshi tanlov. O'rtaga element qo'shish/o'chirishda sekinroq.

LinkedList: List va Deque interface'larini doubly-linked list yordamida implement qiladi. Ro'yxatning istalgan joyiga element qo'shish va o'chirishda samarali. Random access'da (elementga index bo'yicha murojaat qilishda) sekinroq.

HashMap va Hashtable'ni tushuntiring. Ularning farqlari nimada?

HashMap ham, Hashtable ham Map interface'ini implement qiladi va key-value juftliklarini saqlaydi.

HashMap: Synchronized emas (thread-safe emas), bitta null key va bir nechta null qiymatga ruxsat beradi. U odatda tezroq ishlaydi.

Hashtable: Synchronized (thread-safe), null key'larga ham, null qiymatlarga ham ruxsat bermaydi. Synchronization overhead'i tufayli sekinroq.

Java'da Set nima? U List'dan qanday farq qiladi?

Set noyob elementlar to'plamini ifodalaydi. U takroriy elementlarga ruxsat bermaydi va aniq tartibga ega emas. List esa takroriy elementlarga ruxsat beradigan va qo'shilish tartibini (yoki index'ga asoslangan tartibni) saqlaydigan tartiblangan to'plam.

Iterator nima? U collection'lar bilan qanday ishlatiladi?

Iterator — collection'dagi elementlarni birma-bir aylanib chiqishning standart usulini taqdim etadigan interface. U iteration davomida collection'dan elementlarni xavfsiz o'chirish imkonini beradi. U collection sinflarining iterator() method'i orqali ishlatiladi.

Java'dagi multi-threading tushunchasini tushuntiring.

Multi-threading — Java dasturining bitta process ichida turli method'larni yoki kod qismlarini concurrent bajarish qobiliyati. Bajarilishning har bir mustaqil yo'li thread deb ataladi va bu unumdorlik hamda tez javob berish qobiliyatini (responsiveness) yaxshilaydi.

Thread sinfi va Runnable interface'i nima? Thread'ni qanday yaratasiz va ishga tushirasiz?

Thread sinfi: Bu sinf thread'larni bevosita yaratish va boshqarish uchun method'lar taqdim etadi.

Runnable interface'i: Thread tomonidan bajarilishi mumkin bo'lgan vazifani ifodalovchi functional interface. Moslashuvchanlik uchun odatda shu usul afzal ko'riladi (sinf bir nechta interface'ni implement qilishi mumkin).

Thread yaratish uchun:

  1. Thread sinfini extend qiling va run() method'ini override qiling.

  2. Runnable interface'ini implement qiling va uning instance'ini Thread constructor'iga uzating. Thread'ni ishga tushirish uchun Thread obyektida start() method'ini chaqiring, u esa o'z navbatida run() method'ini chaqiradi.

Thread synchronization nima? U nima uchun muhim?

Thread synchronization — thread'larning umumiy resurslarga kirishini nazorat qilish mexanizmi. U ma'lumotlar nomuvofiqligi muammolari va race condition'larning oldini olish hamda bir nechta thread umumiy ma'lumotlarni o'zgartirayotganda data integrity'ni ta'minlash uchun muhim.

synchronized keyword'i va synchronized blokini tushuntiring.

synchronized keyword'i thread synchronization'ga erishish uchun ishlatiladi.

synchronized method: Agar method synchronized bo'lsa, ma'lum bir obyekt uchun uni bir vaqtning o'zida faqat bitta thread bajara oladi.

synchronized block: Muayyan obyektning monitor'i bo'yicha synchronize qilish imkonini beradi va kodning ma'lum bir qismiga kirishni cheklaydi. Bu butun method'ni synchronize qilishga qaraganda nozikroq nazoratni ta'minlaydi.

wait(), notify() va notifyAll() method'lari nima? Ular qachon ishlatiladi?

Bu method'lar (Object sinfidan) thread'lararo aloqa uchun ishlatiladi va synchronized blok ichidan chaqirilishi shart.

  1. wait(): Joriy thread'ning bajarilishini to'xtatib, obyekt monitor'idagi lock'ni bo'shatadi — boshqa thread shu obyektda notify() yoki notifyAll()'ni chaqirguncha yoki kutish vaqti tugaguncha.

  2. notify(): Shu obyekt monitor'ida wait() holatida kutayotgan bitta thread'ni uyg'otadi.

  3. notifyAll(): Shu obyekt monitor'ida wait() holatida kutayotgan barcha thread'larni uyg'otadi.

Multi-threading'da deadlock nima? Uning oldini qanday olish mumkin?

Deadlock ikki yoki undan ortiq thread cheksiz muddatga bloklanib qolganda yuz beradi: ularning har biri ikkinchisi o'ziga kerakli resursni bo'shatishini kutadi. Oldini olish strategiyalari:

  1. Ichma-ich (nested) lock'lardan qoching.

  2. Lock'larni doimo bir xil tartibda oling.

  3. tryLock()'ni timeout bilan ishlating.

  4. Yuqori darajadagi concurrency utility'laridan foydalaning (masalan, java.util.concurrent.locks).

Java'da volatile o'zgaruvchilar nima?

volatile o'zgaruvchi — maxsus turdagi o'zgaruvchi bo'lib, uning qiymati thread'lar tomonidan lokal keshlanmasdan, har doim to'g'ridan-to'g'ri main memory'dan o'qilishi va main memory'ga yozilishi kerakligini bildiradi. Bu bir thread kiritgan o'zgarishlar boshqa thread'larga darhol ko'rinishini ta'minlaydi va concurrent dasturlashdagi visibility muammolarini hal qiladi.

Concurrency'dagi Callable va Future interface'lari nima?

Callable<V>: Runnable'ga o'xshaydi, lekin uning call() method'i V type'idagi natijani qaytarishi va checked exception'larni throw qilishi mumkin. ExecutorService bilan birga ishlatiladi.

Future<V>: Asynchronous hisoblash natijasini ifodalaydi. U hisoblash tugaganini tekshirish, uning tugashini kutish va natijani olish (get()) uchun method'lar taqdim etadi.

Interface'lardagi default method'lar va static method'lar nima?

Java 8'da kiritilgan:

  • Default method'lar: Interface'dagi method implementation'ga ega method'lar. Ular mavjud implement qiluvchi sinflarni buzmasdan interface'larga yangi method'lar qo'shish imkonini beradi. Bu method'larni implement qiluvchi sinflar qayta yozishi (override qilishi) mumkin.

  • Static method'lar: Interface'dagi method implementation'ga ega bo'lgan, biror implement qiluvchi sinf yoki obyektga emas, balki interface'ning o'ziga tegishli method'lar. Ularni to'g'ridan-to'g'ri interface orqali chaqirish mumkin (masalan, MyInterface.staticMethod()).

Functional interface'lar va lambda expression'larni tushuntiring.

Functional interface: Aynan bitta abstract method'ga ega interface. Ular @FunctionalInterface annotation'i bilan belgilanadi (ixtiyoriy, lekin yaxshi amaliyot). Misollar: Runnable, Callable, Comparator.

Lambda expression'lar: Functional interface instance'ini ifodalashning qisqa usuli. Ular yagona abstract method'ni implement qilish uchun ixcham syntax taqdim etadi. Misol: (a, b) -> a + b (add(int a, int b) method'iga ega interface uchun).

Stream API nima? Undan foydalanishga misol keltiring.

Stream API (Java 8) obyektlar to'plamlarini qayta ishlashning kuchli va funksional usulini taqdim etadi. U internal iteration'ni qo'llab-quvvatlaydi va ma'lumotlarni filtering, mapping va reducing kabi amallarni declarative tarzda bajarish imkonini beradi.

Misol:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream()
     .filter(name -> name.startsWith("A"))
     .map(String::toUpperCase)
     .forEach(System.out::println); // Output: ALICE

Optional tushunchasi nima?

Optional<T> — Java 8'da qiymatning mavjudligi yoki yo'qligini ifodalash uchun kiritilgan container obyekt. U dasturchilarni qiymat bo'lmasligi mumkin bo'lgan holatni ochiq-oydin qayta ishlashga majbur qilib, NullPointerExceptions'dan qochishga yordam beradi va mustahkamroq hamda o'qilishi oson kodni rag'batlantiradi.

Fail-fast va fail-safe iterator'lar o'rtasidagi farq nima?

Fail-fast iterator'lar: Iterator yaratilgandan keyin asosiy collection tuzilmaviy jihatdan o'zgartirilsa (masalan, elementlar qo'shilsa/o'chirilsa), iterator'ning o'zining remove() method'i orqali qilingan o'zgarishlardan tashqari holatlarda darhol ConcurrentModificationException throw qiladi. Misollar: ArrayList, HashMap iterator'lari.

Fail-safe iterator'lar: Asosiy collection o'zgartirilsa ham exception throw qilmaydi. Ular collection'ning nusxasi ustida ishlaydi yoki maxsus concurrent ma'lumotlar tuzilmalaridan foydalanadi, shuning uchun asl collection'ga kiritilgan o'zgarishlar iterator'da aks etmaydi. Misollar: ConcurrentHashMap, CopyOnWriteArrayList uchun iterator'lar.

Java'dagi "Pass by Value" tushunchasini tushuntiring.

Java qat'iy ravishda "Pass by Value" tamoyiliga amal qiladi. Bu shuni anglatadiki, method'ga argument uzatilganda argument qiymatining nusxasi yaratiladi va o'sha nusxa uzatiladi.

  1. Primitive data type'lar uchun haqiqiy qiymat nusxalanadi.

  2. Obyekt reference'lari uchun reference'ning o'zi (xotira manzili) nusxalanadi. Shunday qilib, obyekt reference'i qiymat bo'yicha uzatilsa-da, asl reference ham, nusxalangan reference ham bir xil xotira manziliga (heap'dagi bitta obyektga) ishora qiladi. Nusxalangan reference orqali obyektga kiritilgan o'zgarishlar asl obyektga ta'sir qiladi.

Java'da transient keyword'i nima?

transient keyword'i Serializable obyektning instance variable'ini obyektning default serialize qilingan shakliga kirmasligi kerakligini ko'rsatish uchun belgilashda ishlatiladi. Obyekt serialize qilinganda transient field'ning qiymati e'tiborga olinmaydi. Deserialize qilinganda esa u o'zining default qiymati bilan initialize qilinadi (masalan, int uchun 0, obyektlar uchun null).

Java'da ClassLoader'ning roli qanday?

ClassLoader — JRE'ning Java sinflarini JVM'ga dinamik ravishda yuklaydigan qismi. U Java xavfsizlik modelida va sinflarni dinamik yuklashni ta'minlashda hal qiluvchi rol o'ynaydi. Uning Bootstrap, Extension va System ClassLoader kabi turli turlari mavjud.

Java'dagi "immutable obyektlar" tushunchasini tushuntiring.

Immutable obyekt — yaratilgandan keyin state'ini o'zgartirib bo'lmaydigan obyekt. Bunga String sinfi va wrapper class'lar misol bo'ladi. Ularning afzalliklari orasida thread safety (synchronization kerak emas), oson keshlash va HashMap key'larida ishlatish mumkinligi bor. Immutable obyekt yaratish uchun:

  1. Barcha field'larni final va private qilib e'lon qiling.

  2. Setter method'larini taqdim etmang.

  3. Mutable obyektlarni qaytaradigan method'lar defensive copy qaytarishini ta'minlang.

  4. Subclass'larga method'larni override qilishga ruxsat bermang.

Singleton class nima? Singleton class'ni qanday implement qilasiz (masalan, private static Singleton instance va public static Singleton getInstance() yordamida)?

Singleton class — sinfdan faqat bitta instance yaratilishiga cheklov qo'yadigan design pattern. Bu tizim bo'ylab amallarni muvofiqlashtirish uchun aynan bitta obyekt kerak bo'lganda foydali.

Implementation misoli:

public class Singleton {
    // Private static variable to hold the single instance
    private static volatile Singleton instance; // 'volatile' ensures visibility across threads

    // Private constructor to prevent direct instantiation from outside
    private Singleton() {
        // Prevent instantiation via reflection
        if (instance != null) {
            throw new RuntimeException("Use getInstance() to get the single instance.");
        }
    }

    // Public static method to provide the global access point to the instance
    public static Singleton getInstance() {
        if (instance == null) { // First check: no need to synchronize if instance already exists
            synchronized (Singleton.class) { // Synchronize on the class lock
                if (instance == null) { // Second check: ensure only one instance is created
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }

    // Example method
    public void showMessage() {
        System.out.println("Hello from the Singleton!");
    }
}

Professional darajadagi Java intervyu savollari

Java development'da qo'llagan turli design pattern'laringiz haqida gapirib bering.

Eng keng tarqalgan design pattern'lardan ba'zilari:

  1. Singleton: Bu pattern sinfdan faqat bitta instance yaratilishi mumkinligini ta'minlaydi.

  2. Factory Method: Bu pattern aniq sinfni ko'rsatmasdan obyektlar yaratish uchun ishlatiladi.

  3. Builder: Bu pattern murakkab obyektlarni bosqichma-bosqich qurish uchun ishlatiladi.

  4. Observer: Bu pattern publish-subscribe mexanizmini implement qilish uchun juda mos.

  5. Strategy: Algoritmlar oilasini belgilab, ularni o'zaro almashtiriladigan qilmoqchi bo'lganingizda ishlatish uchun ajoyib variant.

  6. Dependency Injection: (Ko'pincha Spring kabi freymvorklar orqali) component'lar dependency'larini boshqarish uchun.

ExecutorService va thread'larni bevosita yaratish o'rtasidagi farqni tushuntiring.

Thread'larni bevosita yaratish (new Thread() orqali): Thread'larni qo'lda yaratadi va boshqaradi. Bu usul ko'plab qisqa muddatli vazifalarda overhead'ga va resurslarning tugab qolishiga olib kelishi mumkin.

ExecutorService: Thread pool'ni boshqaradigan yuqori darajadagi API (java.util.concurrent'ning bir qismi). U vazifalarni topshirishni thread'larda bajarishdan ajratadi, overhead'ni kamaytiradi, resurslardan foydalanishni yaxshilaydi va task queuing, scheduling hamda natijalarni boshqarish (Future) kabi imkoniyatlarni taqdim etadi. Odatda thread guruhlarini boshqarishning afzal ko'riladigan usuli shu.

Garbage collection batafsil qanday ishlaydi? Turli GC algoritmlari haqida gapirib bering.

Garbage collection endi reachable bo'lmagan (ya'ni ularga hali faol bo'lgan birorta ham reference qolmagan) obyektlar ishlatayotgan xotirani aniqlaydi va qaytarib oladi. U odatda bosqichlarda ishlaydi: marking (tirik obyektlarni aniqlash), sweeping (reference qilinmagan joyni qaytarib olish) va ba'zan compacting (xotirani defragmentatsiya qilish).

Turli GC algoritmlariga quyidagilar kiradi:

  1. Serial GC: Bu algoritm single-threaded, ya'ni u GC uchun "dunyoni to'xtatadi" (stop the world). U oddiy client-side ilovalar uchun juda mos.

  2. Parallel GC (Throughput Collector): Bu algoritm GC uchun bir nechta thread'dan foydalanadi, lekin baribir dunyoni to'xtatadi. U yuqori throughput'ga intiladigan ko'p protsessorli tizimlar uchun yaxshi variant.

  3. Concurrent Mark Sweep (CMS) GC: "Dunyoni to'xtatish"ning salbiy ta'sirlarini kamaytirish uchun ishning katta qismini ilova thread'lari bilan concurrent bajarishga harakat qiladi.

  4. G1 (Garbage First) GC: Oldindan aytib bo'ladigan pause vaqtlariga intiladigan region-based, parallel va concurrent collector. Zamonaviy JDK'larda default hisoblanadi.

  5. ZGC/Shenandoah: Juda katta heap'lar va past latency uchun mo'ljallangan, pause'lari qisqa va scalable GC'lar.

Just-In-Time (JIT) compiler'ni va uning JRE'dagi rolini tushuntiring.

JIT compiler — JRE'ning bir qismi. JVM bytecode'ni bajarayotganda JIT compiler "hot spot"larni (tez-tez bajariladigan kod qismlarini) aniqlaydi va ularni runtime davomida native machine code'ga compile qiladi. Bu native kod interpret qilinadigan bytecode'dan ancha tezroq ishlaydi va Java ilovalarining unumdorligini sezilarli darajada oshiradi.

Dependency injection freymvorkidan (masalan, Spring) foydalanishning qanday afzalliklari bor?

DI freymvorklarining eng keng tarqalgan afzalliklaridan ba'zilari:

  1. Decoupling: Hardcode qilingan dependency'larni kamaytiradi va component'larni mustaqilroq qiladi.

  2. Testability: Alohida component'larni mock qilish va testlash osonroq, chunki ular bir-biridan mustaqil.

  3. Reusability: Component'lar qayta ishlatishga yaroqliroq bo'ladi.

  4. Maintainability: O'zgarishlar va yangilanishlarni boshqarish osonroq.

  5. Configuration: Component'larning konfiguratsiyasi markazlashgan bo'ladi.

  6. Boilerplate'ning kamayishi: Obyektlarni yaratish va wiring'ni (qaysi component qayerga inject qilinishini) freymvork o'z zimmasiga oladi.

Java'dagi AOP (Aspect-Oriented Programming) tushunchasini tushuntiring.

Aspect-Oriented Programming (AOP) — cross-cutting concern'larni (logging, xavfsizlik yoki transaction management kabi, boshqacha aytganda, ko'plab modullarda foydali bo'lgan funksionalliklarni) asosiy business logic'dan ajratib, kodingizni tartibli saqlashga yordam beradigan dasturlash yondashuvi. U buni ushbu concern'larni aspect deb ataladigan alohida birliklarda belgilash va so'ngra ularni asosiy kodga join point deb nomlanuvchi muayyan nuqtalarda avtomatik qo'llash orqali amalga oshiradi.

Katta hajmdagi Java ilovasidagi unumdorlik muammosini qanday debug qilgan bo'lardingiz?

Buni qilishning ko'plab turli usullari bor va yaxshiroq natijaga erishish uchun ularning turli kombinatsiyalarini sinab ko'rishingiz mumkin.

Monitoring: Real vaqtdagi metrikalarni (CPU, xotira, thread'lar) olish uchun JMX, VisualVM, JConsole kabi vositalardan foydalaning.

Profiling: CPU hotspot'larini, memory leak'larni va ortiqcha obyekt yaratilishini aniqlash uchun profiler'dan (masalan, YourKit, JProfiler, Async-Profiler) foydalaning.

Thread dump'lar: Bir nechta threaddagi deadlock'larni, bloklangan thread'larni yoki uzoq davom etadigan amallarni aniqlash uchun thread dump'larni tahlil qiling.

Heap dump'lar: Memory leak'larni yoki ayrim obyektlarning haddan tashqari ko'p xotira iste'mol qilishini aniqlash uchun heap dump'larni (Eclipse MAT kabi vositalar yordamida) tahlil qiling.

GC log'lari: GC pause vaqtlari va chastotasini tushunish uchun garbage collection log'larini tahlil qiling.

Code review: Samarasiz algoritmlar, keraksiz obyekt yaratilishi yoki optimallashtirilmagan ma'lumotlar bazasi query'lari bor-yo'qligini aniqlash uchun muhim kod yo'llarini ko'rib chiqing.

JVM HotSpot va OpenJ9 o'rtasidagi farqlar haqida gapirib bering.

Ikkalasi ham mashhur JVM implementation'lari.

  1. HotSpot JVM: Oracle'ning asosiy JVM'i; o'zining ilg'or JIT compiler'i (adaptive optimization, escape analysis) va yuqori darajada optimallashtirilgan garbage collection algoritmlari (G1, CMS) bilan mashhur. Uzoq ishlaydigan ilovalar uchun eng yuqori unumdorlikka e'tibor qaratadi.

  2. OpenJ9 JVM: Eclipse Foundation tomonidan ishlab chiqilgan (IBM'ning hissasi). Tezroq ishga tushishi, xotirani kamroq egallashi va cloud-native muhitdagi yaxshiroq unumdorligi bilan mashhur. U shared class cache va boshqacha JIT compiler arxitekturasidan foydalanadi.

Xavfsiz Java kodi yozishning best practice'lari qanday?

Input validation: Injection hujumlarining (SQL, XSS va h.k.) oldini olish uchun foydalanuvchi kiritgan barcha ma'lumotlarni sanitize va validate qiling.

Access control: To'g'ri authentication va authorization mexanizmlarini implement qiling. Kim nimaga kira olishini nazorat qilish uchun access modifier'lardan (masalan, private, protected) foydalaning.

Log'larda maxfiy ma'lumotlardan qoching: Maxfiy ma'lumotlarni (kredit karta ma'lumotlari, ismlar, telefon raqamlari va h.k.) to'g'ridan-to'g'ri log'larga yozmang.

Exception handling: Ma'lumotlar oshkor bo'lishi yoki kutilmagan xatti-harakatning oldini olish uchun mustahkam exception handling'ni implement qiling. Ba'zan ushlanmagan exception beixtiyor hujumchiga juda ko'p ma'lumot berib qo'yishi mumkin.

Prepared statement'lardan foydalaning: SQL injection'ning oldini olish uchun ma'lumotlar bazasi bilan ishlashda.

API'lardan xavfsiz foydalanish: API'larning xavfsiz versiyalaridan foydalaning (masalan, HTTP o'rniga HTTPS).

Immutable obyektlar: State o'zgarmaydigan joylarda immutable obyektlarni (masalan, String) afzal ko'ring — bu concurrency muammolarini kamaytiradi va kodni xavfsizroq qiladi.

Resurslarni boshqarish: Resource leak'larning oldini olish uchun resurslarni (fayllar, tarmoq ulanishlari) har doim finally bloklarida yoping.

Dependency management: Ma'lum zaifliklarni (vulnerability) yopish uchun kutubxonalar va dependency'larni yangilab turing. Qaysi versiyalarga yangilashingiz mumkinligi va qachon bunday qilish yaxshi fikr emasligi haqida batafsil ma'lumot uchun Semver'ni o'rganib chiqing.

Imtiyozlarni minimallashtiring: Ilovalarni minimal zarur ruxsatlar bilan ishga tushiring.

Yuqori darajada scalable va fault-tolerant Java dasturini qanday loyihalagan bo'lardingiz?

Scalability va fault tolerance — enterprise dunyosida juda talab qilinadigan ikki tushuncha va ularga odatda turli yo'llar bilan erishish mumkin (kontekstingizga qarab):

  • Microservices arxitekturasi: Masshtablashni osonlashtirish va nosozliklarni izolyatsiya qilish uchun tizimni kichikroq, mustaqil service'larga ajrating.

  • Stateless service'lar: Oson horizontal scaling'ga imkon berish uchun service'larni stateless qilib loyihalang.

  • Asynchronous aloqa: Service'larni bir-biridan ajratish (decouple) va yuklamadagi keskin o'sishlarni boshqarish uchun service'lararo aloqada message queue'lardan (Kafka, RabbitMQ) foydalaning.

  • Load balancing: So'rovlarni service'larning bir nechta method instance'lari bo'ylab taqsimlang.

  • Ma'lumotlar bazasini masshtablash: Sharding, replication va keshlash strategiyalarini qo'llang.

  • Circuit breaker'lar: Kaskadli nosozliklarning oldini olish uchun Circuit Breaker kabi pattern'larni (masalan, Resilience4j, Hystrix) implement qiling.

  • Retry'lar va timeout'lar: Tashqi chaqiruvlar uchun mustahkam retry mexanizmlari va oqilona timeout'larni implement qiling.

  • Monitoring va alerting: Keng qamrovli monitoring (log'lar, metrikalar, tracing) va alerting'ni joriy qiling.

  • Containerization/Orchestration: Oson deploy qilish, masshtablash va self-healing uchun Docker va Kubernetes'dan foydalaning.

  • Distributed caching: Ma'lumotlar bazasiga tushadigan yuklamani kamaytirish uchun distributed kesh'lardan (masalan, Redis, Memcached) foydalaning.

  • Idempotency: Retry'larni muammosiz boshqarish uchun imkon qadar amallarni idempotent qilib loyihalang.

Immutability tushunchasini va uning concurrent dasturlashdagi afzalliklarini tushuntiring.

Immutability obyekt state'ini yaratilgandan keyin o'zgartirib bo'lmasligini anglatadi. Concurrent dasturlashda immutable obyektlar ta'rifiga ko'ra thread-safe hisoblanadi, chunki ularning state'i hech qachon o'zgarmaydi — bu synchronization mexanizmlariga bo'lgan ehtiyojni yo'qotadi, concurrency'ni boshqarishni soddalashtiradi va race condition'larning oldini oladi.

CompletableFuture va Future o'rtasidagi farq nima?

  • Future: Asynchronous hisoblash natijasini ifodalaydi, lekin natijalarni bloklamasdan zanjir qilib ulash yoki birlashtirish uchun method'larga ega emas. Odatda isDone() orqali polling qilasiz yoki get() bilan bloklaysiz.

  • CompletableFuture: Future va CompletionStage'ni extend qiladi. U amallarni zanjir qilib ulash (masalan, thenApply, thenCombine), bir nechta Futures'ni birlashtirish va exception'larni funksional uslubda qayta ishlash uchun boy API taqdim etib, non-blocking asynchronous dasturlash imkonini beradi; bu uni reactive programming va bir nechta thread uchun ideal qiladi.

Executor.execute() va ExecutorService.submit() o'rtasidagi farqni tasvirlab bering.

  • Executor.execute(Runnable command): Berilgan Runnable vazifani shunchaki bajaradigan void method. U natija qaytarmaydi va checked exception'larni throw qilmaydi.

  • ExecutorService.submit(Runnable task) / submit(Callable<T> task): Runnable yoki Callable vazifani bajarish uchun topshiradi. U vazifaning holatini tekshirish, uning tugashini kutish yoki natijasini olish uchun ishlatilishi mumkin bo'lgan Future obyektini qaytaradi.

Qachon HashMap yoki Hashtable o'rniga ConcurrentHashMap'dan foydalanasiz?

ConcurrentHashMap'dan bir nechta thread concurrent kira oladigan thread-safe Map kerak bo'lganda foydalanasiz. Hashtable'dan farqli o'laroq (u butun map'ni synchronize qiladi), ConcurrentHashMap fine-grained locking mexanizmidan foydalanadi; bu o'qish ko'p bo'lgan yoki yozish o'rtacha darajada ko'p bo'lgan workload'larda Hashtable'ga qaraganda yuqoriroq concurrency va yaxshiroq unumdorlikka imkon beradi.

ThreadLocal o'zgaruvchi tushunchasini tushuntiring.

ThreadLocal o'zgaruvchi har bir thread uchun o'ziga xos bo'lgan ma'lumotlarni saqlash imkonini beradi. ThreadLocal o'zgaruvchiga murojaat qiladigan har bir thread o'zgaruvchining mustaqil ravishda initialize qilingan o'z nusxasini oladi. Bu umumiy obyektga kirishni synchronize qilish o'rniga har bir thread'ga obyektning alohida nusxasini taqdim etish orqali race condition'lardan qochishda foydali.

Java'dagi record type'lar (Java 14'da kiritilgan) nima va ulardan qachon foydalanasiz?

Record type'lar — immutable ma'lumotlarni shaffof tashuvchi sifatida ishlashga mo'ljallangan sinf turi. Ular mohiyatan data tuple'lardan iborat bo'lgan sinflarni e'lon qilish uchun ixcham syntax taqdim etadi va constructor'lar, getter'lar, equals(), hashCode() hamda toString()'ni avtomatik generatsiya qiladi. Ulardan DTO'lar (Data Transfer Object'lar), oddiy ma'lumot container'lari yoki method'larning return type'lari uchun — boilerplate'siz immutable ma'lumotlarni modellashtirish kerak bo'lgan joylarda foydalanasiz.

try-with-resources statement'i haqida gapirib bering.

try-with-resources statement'i (Java 7'da kiritilgan) AutoCloseable interface'ini implement qiladigan resurslarni (masalan, Scanner class, FileInputStream) avtomatik yopish orqali resurslarni boshqarishni soddalashtiradi. U resurslarni yopish uchun ochiq-oydin finally bloklariga bo'lgan ehtiyojni yo'qotadi, bu esa kodni tozaroq va xatolarga kamroq moyil qiladi. Misol:

try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
    // use br
} catch (IOException e) {
    // handle exception
}

Java ilovalarida qanday memory leak'lar ko'p uchraydi va ularni qanday aniqlaysiz?

Keng tarqalgan memory leak'larga quyidagilar kirishi mumkin:

  • Yopilmagan resurslar: Yopilmay qolgan ochiq stream'lar, ulanishlar yoki fayllar.

  • Static collection'lar: Static collection'larda obyektlarga reference'larni cheksiz saqlab qolish (chunki ularning reference'i hech qachon bo'shatilmaydi).

  • Inner class reference'lari: Non-static inner class'larning tashqi sinf instance'lariga yashirin reference saqlab, GC'ga to'sqinlik qilishi.

  • Noto'g'ri equals()/hashCode(): HashMap yoki HashSet kabi collection'lardan foydalanganda, agar bu method'lar to'g'ri implement qilinmagan bo'lsa, obyektlar to'g'ri o'chirilmasligi mumkin.

  • ThreadLocal'dan haddan tashqari ko'p foydalanish: Thread pool'larda thread tugaganidan keyin ThreadLocal o'zgaruvchilar to'g'ri tozalanmasa.

Aniqlash uchun quyidagilardan foydalaniladi:

  • Heap dump tahlili: Heap dump'larni tahlil qilish va xotirada ushlanib qolgan obyektlarni aniqlash uchun Eclipse MAT kabi vositalar.

  • Profiler'lar: Vaqt o'tishi bilan heap'dan foydalanishni kuzatish va garbage collection qilinmayotgan obyektlarni aniq topish uchun VisualVM, JProfiler, YourKit kabi vositalar.

  • GC log'lari: Tez-tez sodir bo'ladigan full GC'larni yoki GC'dan oldin heap'dan foydalanishning ortib borishini aniqlash uchun GC log'larini tahlil qilish.

JVM'dagi "class loading" tushunchasini va uning bosqichlarini tushuntiring.

Class loading — JVM sinflarni xotiraga yuklaydigan jarayon. U uchta asosiy bosqichdan iborat:

  • Loading: Sinf uchun bytecode'ni topadi va yuklaydi hamda Method Area'da Class obyektini yaratadi.

  • Linking:

    • Verification: Yuklangan bytecode'ning tuzilmaviy to'g'riligi va xavfsizligini tekshiradi.

    • Preparation: Static variable'lar uchun xotira ajratadi va ularni default qiymatiga initialize qiladi.

    • Resolution: Constant pool'dagi symbolic reference'larni to'g'ridan-to'g'ri reference'lar bilan almashtiradi (masalan, method manzillari, field offset'lari).

  • Initialization: Sinfning static initializer'larini bajaradi va kodda ochiq-oydin belgilangan static variable'larga boshlang'ich qiymatlarni beradi. Bu sinfdan birinchi faol foydalanishdan bevosita oldin sodir bo'ladi.

Freymvorklarda reflection API'lar odatda nima uchun ishlatiladi?

Reflection API'lar freymvorklarda quyidagilar uchun keng qo'llaniladi:

  • Dependency Injection (masalan, Spring): Annotation'lar yoki konfiguratsiya asosida bean'larni dinamik instantiate qilish, dependency'larni inject qilish va method'larni chaqirish uchun.

  • Object-Relational Mapping (Hibernate kabi ORM): Runtime environment'da sinf field'lari va annotation'larini tekshirib, Java obyektlarini ma'lumotlar bazasi jadvallariga map qilish uchun.

  • Testlash freymvorklari (masalan, JUnit, Mockito): Test method'larini topish, mock'larni inject qilish va assertion'larni bajarish uchun.

  • Serialization/deserialization kutubxonalari (masalan, Jackson, Gson): Obyekt tuzilmalarini tekshirib, Java obyektlarini JSON/XML'ga va aksincha o'girish uchun.

  • Dynamic proxy'lar: Runtime'da muayyan interface'larni implement qiladigan proxy obyektlarni yaratish; ko'pincha AOP uchun ishlatiladi.

Java ilovasida thread safety'ni qanday ta'minlaysiz?

Thread safety'ni ta'minlash uchun foydalanishingiz mumkin bo'lgan ba'zi usullar:

  • Synchronization: Umumiy mutable ma'lumotlarni himoya qilish uchun synchronized keyword'idan (method'lar yoki synchronized blok) foydalaning.

  • Lock'lar: Moslashuvchanroq locking mexanizmlari uchun ochiq-oydin java.util.concurrent.locks'dan (ReentrantLock, ReadWriteLock) foydalaning.

  • Volatile o'zgaruvchilar: Qiymatlari barcha thread'larga darhol ko'rinishi kerak bo'lgan field'lar uchun volatile'dan foydalaning.

  • Atomic o'zgaruvchilar: Ochiq-oydin locking'siz alohida o'zgaruvchilar ustida atomic amallar bajarish uchun java.util.concurrent.atomic sinflaridan (masalan, AtomicInteger, AtomicReference) foydalaning.

  • Concurrent collection'lar: ConcurrentHashMap, CopyOnWriteArrayList, BlockingQueue kabi thread-safe Java Collections'dan foydalaning.

  • Immutability: Synchronization ehtiyojini yo'qotish uchun immutable obyektlarni loyihalang.

  • ThreadLocal: Har bir thread uchun noyob bo'lishi kerak bo'lgan ma'lumotlar uchun ThreadLocal'dan foydalaning.

  • ExecutorService: ExecutorService va Future yordamida thread'lar va vazifalarni samarali boshqaring.

NPE (NullPointerException) tushunchasini va undan qanday qochish mumkinligini tushuntiring.

NullPointerException runtime davomida ilova obyekt talab qilinadigan kontekstda null reference'dan foydalanishga uringanda yuz beradi (masalan, null obyektda method chaqirish, null obyektning field'iga murojaat qilish yoki null massivning elementiga murojaat qilish).

Undan qochish uchun quyidagilarni qilishingiz mumkin:

  • Null tekshiruvlari: Obyektdan foydalanishdan oldin uning null emasligini ochiq-oydin tekshiring (if (obj != null)).

  • Optional: null qaytarishi mumkin bo'lgan method'lar uchun java.util.Optional'dan (Java 8+) foydalaning — bu chaqiruvchilarni qiymat yo'qligi holatini qayta ishlashga majbur qiladi.

  • Defensive programming: Method argumentlari null emasligiga ishonch hosil qilish uchun ularni validate qiling.

  • Annotation'lar: Static analysis vositalari uchun @NonNull yoki @Nullable kabi annotation'lardan foydalaning.

  • null collection'larni qaytarmang: Method'lardan null o'rniga bo'sh collection'larni qaytaring.

Java'da Error va Exception o'rtasidagi farq nima?

Error ham, Exception ham Throwable'ning subclass'lari.

  • Error: Oqilona yozilgan ilova ushlashga urinmasligi kerak bo'lgan jiddiy muammolarni ifodalaydi. Ular odatda JVM muhitining o'zi bilan bog'liq bo'lgan, tiklab bo'lmaydigan holatlarni bildiradi (masalan, OutOfMemoryError, StackOverflowError).

  • Exception: Ilova ushlab, qayta ishlashni xohlashi mumkin bo'lgan holatlarni ifodalaydi. Bular dasturning odatiy bajarilishi davomida yuz beradigan, lekin ulardan ohista tiklanish mumkin bo'lgan muammolar.

Java'dagi SOLID design tamoyillari haqida gapirib bering.

SOLID — dasturiy ta'minot dizaynini tushunarliroq, moslashuvchanroq va qo'llab-quvvatlashga qulayroq qiladigan beshta design tamoyilining qisqartmasi.

  • S - Single Responsibility Principle: Sinfning faqat bitta vazifasi bo'lishi kerak.

  • O - Open/Closed Principle: Dasturiy entity'lar (sinflar, modullar, funksiyalar va h.k.) kengaytirish uchun ochiq, lekin o'zgartirish uchun yopiq bo'lishi kerak.

  • L - Liskov Substitution Principle: Dasturdagi obyektlarni dasturning to'g'riligini buzmasdan ularning subtype'lari instance'lari bilan almashtirish mumkin bo'lishi kerak (class Dog extends Animal).

  • I - Interface Segregation Principle: Client'lar o'zlari foydalanmaydigan interface'larga bog'liq bo'lishga majbur qilinmasligi kerak.

  • D - Dependency Inversion Principle: Yuqori darajadagi kod to'g'ridan-to'g'ri past darajadagi kodga tayanmasligi kerak. Buning o'rniga ikkalasi ham interface yoki abstract class kabi abstraction'larga tayanishi kerak. Bu kodingizni moslashuvchanroq va o'zgartirishga osonroq qiladi.

Java ilovasida ma'lumotlar bazasi bilan ishlashni qanday optimallashtirasiz?

  • Connection pooling: Ma'lumotlar bazasi ulanishlarini qayta ishlatish uchun connection pool'dan (masalan, HikariCP, C3P0) foydalaning.

  • Prepared statement'lar: SQL injection'ning oldini olish va SQL'ning oldindan compile qilinishi tufayli yaxshiroq unumdorlik uchun PreparedStatement'dan foydalaning.

  • Batch processing: Tarmoq orqali round-trip'lar sonini kamaytirish uchun bir nechta ma'lumotlar bazasi amallarini bitta batch so'roviga guruhlang.

  • Lazy loading va eager loading: Faqat kerakli ma'lumotlarni olish uchun ORM freymvorklarida lazy va eager loading o'rtasida oqilona tanlov qiling.

  • Keshlash: Tez-tez murojaat qilinadigan, kam o'zgaradigan ma'lumotlar uchun keshlash qatlamlarini (masalan, Ehcache, Redis) joriy qiling.

  • Ma'lumotlar bazasiga asynchronous kirish: Juda yuqori throughput uchun non-blocking ma'lumotlar bazasi driver'larini (masalan, R2DBC) yoki asynchronous pattern'larni ko'rib chiqing.

  • Transaction'lar: Ma'lumotlar izchilligini ta'minlash va lock contention'ni minimallashtirish uchun to'g'ri transaction management'dan foydalaning.

  • N+1 select'lardan qoching: N ta bog'liq entity uchun N ta qo'shimcha query bajarmaslik uchun ORM query'larini optimallashtiring.

Java'dagi AOT (Ahead-of-Time) compilation tushunchasini tushuntiring.

AOT (Ahead-of-Time) compilation — bytecode'ni Java dasturi ishga tushirilishidan oldin, odatda build bosqichida native machine code'ga compile qilish. Bu runtime'da sodir bo'ladigan JIT compilation'dan farq qiladi. AOT JIT warm-up bosqichini yo'qotish orqali ishga tushish vaqtini yaxshilashi va xotira sarfini kamaytirishi mumkin (ayniqsa kichikroq ilovalar yoki serverless funksiyalar uchun), lekin u runtime bajarilish profillari asosida optimallashtiradigan JIT compiler bilan bir xil eng yuqori unumdorlikka erisha olmasligi mumkin. GraalVM Native Image bunga yaqqol misol.

Java'da thread pool'larni implement qilishning turli usullari haqida gapirib bering.

Thread pool'lar java.util.concurrent'dagi Executor va ExecutorService interface'lari yordamida implement qilinadi. Keng tarqalgan implementation'larga quyidagilar kiradi:

  • Executors.newFixedThreadPool(int nThreads): Qat'iy o'lchamdagi thread pool yaratadi.

  • Executors.newCachedThreadPool(): Mavjud thread'lar bo'sh bo'lganda ularni qayta ishlatadigan, lekin kerak bo'lsa yangilarini yaratadigan moslashuvchan pool yaratadi. Juda uzoq vaqt bo'sh turgan thread'lar to'xtatiladi.

  • Executors.newSingleThreadExecutor(): Vazifalarning ketma-ket bajarilishini ta'minlaydigan single-thread executor yaratadi.

  • Executors.newScheduledThreadPool(int corePoolSize): Vazifalarni ma'lum kechikishdan keyin yoki davriy ravishda ishga tushirishni rejalashtirish uchun.

  • ThreadPoolExecutor: Eng moslashuvchan implementation bo'lib, core pool size, maximum pool size, keep-alive time, work queue turi va rejection policy'ni sozlash imkonini beradi. Bu bir nechta thread qanday boshqarilishi ustidan nozik nazoratni ta'minlaydi.

Performance tuning uchun qanday JVM option'lari bor?

Performance tuning uchun turli JVM option'laridan foydalanish mumkin:

  • Heap o'lchami: -Xms<size> (boshlang'ich heap o'lchami) va -Xmx<size> (maksimal heap o'lchami).

  • Garbage collector: GC algoritmini tanlash uchun -XX:+UseG1GC, -XX:+UseParallelGC, -XX:+UseZGC, -XX:+UseShenandoahGC.

  • GC logging: Batafsil GC chiqishi uchun -Xlog:gc yoki -XX:+PrintGCDetails -XX:+PrintGCTimeStamps.

  • JIT compiler: -XX:TieredStopAtLevel=1 (tezroq ishga tushish uchun) yoki inlining'ni nazorat qilish uchun -XX:MaxInlineSize kabi option'lar.

  • Boshqalar: -XX:+UseCompressedOops (64-bit JVM'larda obyekt pointer'larini optimallashtirish uchun), -Djava.awt.headless=true (server-side ilovalar uchun).

Java'da reactive programming'dagi backpressure tushunchasini tushuntiring.

Backpressure — reactive programming'dagi (masalan, Project Reactor yoki RxJava bilan) mexanizm bo'lib, u consumer'ga producer'ga o'zi haddan tashqari yuklanganini va joriy tezlikda boshqa ma'lumotlarni qayta ishlay olmasligini bildirish imkonini beradi.

Bu producer consumer'ni ma'lumotlar bilan to'ldirib yuborishining oldini oladi — aks holda resurslar tugab qolishi yoki OutOfMemoryError yuz berishi mumkin. Consumer producer'dan ma'lum miqdordagi elementlarni ochiq-oydin so'raydi va shu tariqa producer ma'lumotlarni tartibsiz uzatishi o'rniga ma'lumotlar oqimi ustidan nazoratni ta'minlaydi.

Katta Java ilovasi uchun mustahkam logging strategiyasini qanday loyihalagan bo'lardingiz?

Katta Java ilovasi uchun mustahkam logging strategiyasi quyidagilarni o'z ichiga oladi:

Yo'l xaritalariQo'llanmalarFAQYouTube

yo'lxaritaroadmap.shasosida

Hamjamiyat tomonidan yaratilgan yo'l xaritalari, eng yaxshi amaliyotlar, loyihalar, maqolalar, manbalar va yo'nalishlar — o'z yo'lingizni tanlash va kasbingizda o'sish uchun.

© yo'lxarita·Shartlar·Maxfiylik·

roadmap.sh

Barcha kontent roadmap.sh loyihasidan olingan (© Kamran Ahmed) va shaxsiy o'rganish uchun o'zbek tiliga tarjima qilinmoqda.

Qidiruv

Yo'l xaritalari, loyihalar va savollarni qidiring