CodeGym /Kurslar /JAVA 25 SELF /Generics: nə üçün lazımdır, əsas sintaksis

Generics: nə üçün lazımdır, əsas sintaksis

JAVA 25 SELF
Səviyyə , Dərs
Mövcuddur

1. “Xam” kolleksiyaların problemi (raw types)

Qısaca tarixçəyə nəzər salaq. Java 5-ə qədər bütün kolleksiyalar “hərşeyyeyən” idi. Onlar Object tipli obyektləri saxlayırdı və kompilyator ora nə qoyduğunuzu nəzarətdə saxlamırdı. Sətir qoymaq istəyirsiniz? Buyurun. Rəqəm? Niyə də yox. Pişik? O da olar.

// "xam" kolleksiyalar (raw types) nümunəsi, Java 5-dən əvvəl
List list = new ArrayList();
list.add("Salam");
list.add(42);
list.add(new Object());

Problem isə dəyəri “çıxarıb” istifadə edəndə üzə çıxırdı:

String s = (String) list.get(0); // OK, bu String-dir
String s2 = (String) list.get(1); // BAM! ClassCastException

Kompilyator susur, amma run-time-da siz ClassCastException alırsınız. Bu elə bil üzərində “alma” yazılmış qutudur, içində isə fincan, banan və kirpi var.

Bu niyə pisdir?

  • Xətalar yalnız icra zamanı üzə çıxır.
  • Tiplər qarışır: obyektləri tələb olunan tipə əl ilə çevirmək (cast) lazım olur.
  • Kod daha az oxunaqlıdır və daha risklidir.

Həll — generics (ümumiləşdirmələr)

Generics (ümumiləşdirmələr) — tiplə parametrizə olunan siniflər, interfeyslər və metodlar yaratmağa imkan verən mexanizmdir. Yəni kolleksiyaya deyirsiniz: “Yalnız String-ləri saxla”, kompilyator da buna ciddi nəzarət edir.

List<String> words = new ArrayList<>();
words.add("Salam");
words.add("Dünya");
// words.add(42); // Kompilyasiya xətası! List<String>-ə int əlavə etmək olmaz

İndi kompilyator siyahıya sətirdən başqa heç nə qoymağa imkan vermir. Xəta proqram işə düşməmişdən əvvəl tutulur.

Generics-in əsas ideyası:
Kolleksiyalar (və təkcə onlar deyil) üçün tip təhlükəsizliyini təmin etmək ki, xətalar run-time-da yox, kompilyasiya mərhələsində tutulsun.

2. Generics sintaksisi: kodda necə görünür

Tipin bucaqlı mötərizələrdə göstərilməsi

Kolleksiya yaradanda, elementlərin tipini <> içində göstərin:

List<String> names = new ArrayList<>();
names.add("Alisa");
names.add("Bob");
// names.add(123); // Xəta: String-lər siyahısına rəqəm əlavə etmək olmaz

String first = names.get(0); // Tip çevirməyə ehtiyac yoxdur!

Klassika:

  • List<String> — String-lər siyahısı
  • List<Integer> — Integer-lər siyahısı
  • Set<Double> — Double-lər çoxluğu
  • Map<String, Integer> — açar String, dəyər Integer

Niyə sadəcə List yazmaq olmaz?

Mümkündür, amma generics-in bütün üstünlüklərini itirirsiniz və kompilyator xəbərdarlıq edəcək:

List list = new ArrayList(); // raw type — tövsiyə edilmir!
list.add("Hello");
list.add(7.5);
String s = (String) list.get(1); // Salam, ClassCastException!

Müasir Java kodu həmişə generics-dən istifadə edir.

Diamond operatoru <>

Java 7-dən etibarən, əgər tip kontekstdən aydındırsa, sağ tərəfdə onu yazmaya bilərsiniz:

List<String> list = new ArrayList<>(); // Kompilyator özü anlayacaq ki, burada <String> var

3. Müxtəlif kolleksiyalar üçün generics

List, Set, Map üçün nümunələr

List<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(20);

Set<String> uniqueNames = new HashSet<>();
uniqueNames.add("Alisa");
uniqueNames.add("Bob");

Map<String, Integer> ages = new HashMap<>();
ages.put("Alisa", 23);
ages.put("Bob", 31);

Öz sinfinizlə nümunə

class Student {
    String name;
    int age;
    // ...
}

List<Student> students = new ArrayList<>();
students.add(new Student());

4. Faydalı nüanslar

Generics-in üstünlükləri

Tip təhlükəsizliyi. Kompilyator kolleksiyaya yalnız lazım olan tipdə elementlərin düşməsinə nəzarət edir.

Tip çevirməyə ehtiyac yoxdur. Əvvəl: String s = (String) list.get(0);. İndi: String s = list.get(0);.

Kod daha oxunaqlı və etibarlıdır. Run-time-da daha az sürpriz.

Generics məhdudiyyətləri

Primitiv tiplərdən istifadə etmək olmaz. Ümumiləşdirmələr yalnız obyektlərlə işləyir, primitivlərlə yox (int, double, boolean). Qablaşdırıcı siniflərdən istifadə edin: Integer, Double, Boolean.

List<Integer> numbers = new ArrayList<>();
numbers.add(10); // int avtomatik olaraq Integer-ə çevrilir (autoboxing)

Tip silinməsi (type erasure) haqqında qısa məlumat

Java-da generics tip silinməsi mexanizmi ilə reallaşdırılıb: kompilyasiyadan sonra tip parametrləri barədə məlumat silinir və run-time-da JVM bunun List<String> yox, sadəcə List olduğunu bilmir. Bu, geriyə uyğunluq naminə edilib.

Nəticə: tip arqumentini konkret dəyərlə instanceof vasitəsilə yoxlamaq olmaz.

List<String> list = new ArrayList<>();
// if (list instanceof List<String>) { ... } // Kompilyasiya xətası!

Başqa tipdən element əlavə etməyə cəhd — kompilyasiya xətası

List<String> words = new ArrayList<>();
words.add("Hello");
// words.add(123); // Kompilyasiya xətası: incompatible types: int cannot be converted to String

Map<String, Integer> map = new HashMap<>();
map.put("Pişik", 5);
// map.put(3, "Fil"); // Xəta: açar String olmalıdır, dəyər — Integer

Və bu əladır: xətalar kompilyasiya mərhələsində tutulur.

Yalnız kolleksiyalar deyil

Generics-i öz siniflərinizdə və metodlarınızda da istifadə edə bilərsiniz. Məsələn, universall “Qutu”:

class Box<T> {
    private T value;

    public void set(T value) { this.value = value; }
    public T get() { return value; }
}

Box<String> stringBox = new Box<>();
stringBox.set("Salam");
System.out.println(stringBox.get());

Box<Integer> intBox = new Box<>();
intBox.set(42);
System.out.println(intBox.get());

Kolleksiyalarda generics — standartdır, amma onları başqa yerlərdə də görəcəksiniz, məsələn, Stream APIOptional-da.

5. Generics ilə işləyərkən tipik səhvlər

Səhv №1: “xam” kolleksiyalardan istifadə. List list = new ArrayList(); kimi yazılış tip təhlükəsizliyini aradan qaldırır. Həmişə tip parametrlərini göstərin, məsələn, List<String>.

Səhv №2: Primitivlərdən istifadə etməyə cəhd. List<int> yazmaq olmaz, List<Integer> istifadə edin.

Səhv №3: Kolleksiyadan oxuyarkən əl ilə tip çevirmə. Əgər generics istifadə edirsinizsə, (String) list.get(i) kimi çevirməyə ehtiyac yoxdur. Əgər lazımdırsa — haradasa tipləri pozmusunuz.

Səhv №4: Tip parametrlərinin run-time-da əlçatan olacağını gözləmək. Tip silinməsi səbəbindən onları instanceof ilə List<String> kimi yoxlamaq olmaz.

Səhv №5: Bir kolleksiyada fərqli tipləri qarışdırmaq. Əgər List<String> elan edilibsə, Integer əlavə etməyə çalışmayın — kompilyator buraxmayacaq və bu, yaxşıdır.

1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Rəqəmsal kitabxanamın kataloqu 📚✍️
Rəqəmsal kitabxanamın kataloqu 📚✍️
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Sehrli universal sandıqlar 📦✨
Sehrli universal sandıqlar 📦✨
1
Sorğu/viktorina
, səviyyə, dərs
Əlçatan deyil
Kolleksiyalar və generics
Kolleksiyalar və generics
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION