19. Generics

Oldingi bobda Collections bilan tanishdik.

Masalan:

ArrayList<String> ismlar = new ArrayList<>();

Bu yerda String oddiy ma'lumot turi emas, balki ArrayList ichida qanday turdagi ma'lumot saqlanishini bildiradi.

Bu tushuncha Generics deb ataladi.

Generics nima?

Generics — class, interface va methodlarni ma'lum bir data type bilan xavfsiz ishlashga imkon beradigan Java mexanizmi.

Masalan:

ArrayList<String> ismlar = new ArrayList<>();

Bu ArrayList faqat String saqlashini bildiradi.

Quyidagi kod ishlamaydi:

ismlar.add(100);

Chunki 100Integer, ismlar esa String uchun yaratilgan.

Nima uchun Generics kerak?

Genericsning asosiy afzalligi — type safety.

Masalan, genericsiz:

ArrayList list = new ArrayList();

list.add("Ali");
list.add(100);
list.add(true);

Bitta list ichida turli xil ma'lumotlar paydo bo‘ldi.

Keyinchalik qaysi element qanday type ekanini tekshirishga to‘g‘ri keladi.

Generics bilan:

ArrayList<String> list = new ArrayList<>();

list.add("Ali");
list.add("Vali");
list.add("Hasan");

Endi Java list faqat String saqlashini biladi.

Generic type belgisi

Ko‘pincha generic type uchun T harfi ishlatiladi.

Masalan:

class Box<T> {

    T qiymat;
}

Bu yerda T keyinchalik qanday type bo‘lishini bildiradi.

Generic class

O‘zimiz generic class yaratishimiz mumkin.

class Box<T> {

    private T qiymat;

    public void set(T qiymat) {
        this.qiymat = qiymat;
    }

    public T get() {
        return qiymat;
    }
}

Endi Box bilan String ishlatamiz:

Box<String> box = new Box<>();

box.set("Salom");

System.out.println(box.get());

Natija:

Salom

Integer bilan ham ishlatish mumkin:

Box<Integer> box = new Box<>();

box.set(100);

System.out.println(box.get());

Natija:

100

Bitta class turli type bilan ishlayapti.

Generic classning to‘liq misoli

class Box<T> {

    private T qiymat;

    public Box(T qiymat) {
        this.qiymat = qiymat;
    }

    public T get() {
        return qiymat;
    }
}

Keyin:

public class Main {

    public static void main(String[] args) {

        Box<String> matn = new Box<>("Salom");

        Box<Integer> son = new Box<>(100);

        System.out.println(matn.get());
        System.out.println(son.get());
    }
}

Natija:

Salom
100

Bir nechta generic type

Generic class bir nechta type qabul qilishi mumkin.

Masalan:

class Pair<K, V> {

    private K key;
    private V value;

    public Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public K getKey() {
        return key;
    }

    public V getValue() {
        return value;
    }
}

Endi:

Pair<String, Integer> odam = new Pair<>("Ali", 25);

Bu yerda:

K → String
V → Integer

Key:

Ali

Value:

25

Generic method

Method ham generic bo‘lishi mumkin.

Masalan:

public static <T> void print(T qiymat) {

    System.out.println(qiymat);
}

Endi:

print("Salom");
print(100);
print(3.14);

Natija:

Salom
100
3.14

Method turli type bilan ishlayapti.

Generic methodning to‘liq misoli

public class Main {

    public static <T> void print(T qiymat) {

        System.out.println(qiymat);
    }

    public static void main(String[] args) {

        print("Salom");
        print(100);
        print(true);
    }
}

Generic type nomlari

Java'da generic type uchun odatda quyidagi harflar ishlatiladi:

T → Type
E → Element
K → Key
V → Value
N → Number

Masalan:

class Box<T> {
}

yoki:

class Pair<K, V> {
}

Bu nomlar majburiy emas.

Masalan, T o‘rniga X yozish ham mumkin:

class Box<X> {

    X qiymat;
}

Lekin Java dasturchilari odatda standart nomlardan foydalanadilar.

Generics va primitive type

Generics bilan primitive type ishlatib bo‘lmaydi.

Masalan, bu noto‘g‘ri:

ArrayList<int> sonlar = new ArrayList<>();

Buning o‘rniga wrapper class ishlatiladi:

ArrayList<Integer> sonlar = new ArrayList<>();

Xuddi shunday:

int     → Integer
double  → Double
float   → Float
boolean → Boolean
char    → Character
long    → Long

Masalan:

ArrayList<Integer> sonlar = new ArrayList<>();

sonlar.add(10);
sonlar.add(20);
sonlar.add(30);

Generic va type safety

Generics koddagi xatolarni oldindan aniqlashga yordam beradi.

Masalan:

ArrayList<String> ismlar = new ArrayList<>();

ismlar.add("Ali");
ismlar.add("Vali");

Keyin:

String ism = ismlar.get(0);

Bu xavfsiz, chunki Java ismlar ichida faqat String borligini biladi.

Generics Collections bilan

Generics eng ko‘p Collections bilan ishlatiladi.

Masalan:

ArrayList<String> ismlar = new ArrayList<>();

HashSet<Integer> sonlar = new HashSet<>();

HashMap<String, Integer> yoshlar = new HashMap<>();

Bu yerda:

ArrayList<String>

faqat String saqlaydi.

HashSet<Integer>

faqat Integer saqlaydi.

HashMap<String, Integer>

esa String key va Integer value saqlaydi.

Real hayotdagi misol

Tasavvur qiling, sizda mahsulotlar bilan ishlaydigan dastur bor.

class Product {

    String name;
    double price;

    Product(String name, double price) {
        this.name = name;
        this.price = price;
    }
}

Mahsulotlar ro‘yxatini yaratamiz:

ArrayList<Product> products = new ArrayList<>();

Endi:

products.add(new Product("Laptop", 1000));
products.add(new Product("Phone", 700));
products.add(new Product("Mouse", 30));

Bu yerda Java products faqat Product obyektlarini saqlashini biladi.

Genericsning asosiy foydalari

Generics:

  • Type safety beradi.
  • Kodni qayta ishlatishga yordam beradi.
  • Type castingni kamaytiradi.
  • Collections bilan xavfsiz ishlash imkonini beradi.
  • Generic class va methodlar yaratish imkonini beradi.

Amaliy mashqlar

1-mashq

Quyidagi generic classni yarating:

class Box<T> {

    T qiymat;
}

String va Integer bilan ishlatib ko‘ring.

2-mashq

Pair<K, V> generic class yarating.

Unda key va value bo‘lsin.

Masalan:

Pair<String, Integer>

ko‘rinishida foydalaning.

3-mashq

Generic method yarating:

public static <T> void print(T qiymat)

Uni String, Integer va Double bilan chaqiring.

4-mashq

Quyidagi Collectionslarni yarating:

ArrayList<String>
HashSet<Integer>
HashMap<String, Double>

Har biriga mos ma'lumotlar qo‘shing.

Muhim narsalarni eslab qoling

Generics — type bilan xavfsiz va qayta ishlatiladigan kod yozish imkonini beradi.

Generic class:

class Box<T> {
}

Generic object:

Box<String> box = new Box<>();

Bir nechta type:

class Pair<K, V> {
}

Generic method:

public static <T> void print(T qiymat) {
}

Collections bilan:

ArrayList<String>
HashSet<Integer>
HashMap<String, Integer>

Generics Java'da katta dasturlar yozishda juda muhim tushuncha hisoblanadi.