JavaRush /Java Blogu /Random-AZ /Java-da generiklər nədir

Java-da generiklər nədir

Qrupda dərc edilmişdir
Salam! Bu gün generiklər haqqında danışacağıq. Deməliyəm ki, siz çoxlu yeni şeylər öyrənəcəksiniz! Təkcə bu deyil, növbəti bir neçə mühazirə də generiklərə həsr olunacaq. Java-da generiklər nədir - 1 Buna görə də, bu mövzu sizin üçün maraqlıdırsa, şanslısınız: bu gün generiklərin xüsusiyyətləri haqqında çox şey öyrənəcəksiniz. Yaxşı, yoxsa, sakitləş və rahatla! :) Bu çox vacib mövzudur və bunu bilmək lazımdır. Sadə birindən başlayaq: “nə” və “niyə”. Generiklər nədir? Generiklər parametrli növlərdir. Ümumilik yaradarkən, siz yalnız onun növünü deyil, həm də onunla işləməli olan məlumat növünü təyin edirsiniz. Düşünürəm ki, ən bariz nümunə artıq ağlınıza gəlib - bu ArrayList! Biz onu adətən proqramda necə yaradırıq:
import java.util.ArrayList;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<String> myList1 = new ArrayList<>();
       myList1.add("Test String 1");
       myList1.add("Test String 2");
   }
}
Təxmin etdiyiniz kimi, siyahının özəlliyi ondadır ki, ona hər şeyi “doldurmaq” mümkün olmayacaq: o, yalnız obyektlərlə işləyir String. İndi Java tarixinə qısa bir ekskursiya edək və “niyə?” sualına cavab verməyə çalışaq. Bunun üçün özümüz ArrayList sinfinin sadələşdirilmiş versiyasını yazacağıq. Siyahımız yalnız daxili seriala məlumat əlavə edə və bu məlumatları qəbul edə bilər:
public class MyListClass {

   private Object[] data;
   private int count;

   public MyListClass() {
       this.data = new Object[10];
       this.count = 0;
   }

   public void add(Object o) {
       this.data[count] = o;
       count++;
   }

   public Object[] getData() {
       return data;
   }
}
Tutaq ki, biz siyahımızda yalnız nömrələri saxlamağı istəyirik Integer. Bizdə generiklər yoxdur. IntegerBiz açıq şəkildə yoxlanış nümunəsini göstərə bilmərik add(). Onda bütün sinifimiz yalnız üçün uyğun olacaq Integervə biz dünyada mövcud olan bütün məlumat növləri üçün eyni sinfi yazmalı olacağıq! Proqramçılarımıza güvənmək qərarına gəldik və orada lazımsız bir şey əlavə etməmələri üçün kodda sadəcə bir şərh buraxın:
//use it ONLY with Integer data type
public void add(Object o) {
   this.data[count] = o;
   count++;
}
Proqramçılardan biri bu şərhi əldən verdi və səhvən siyahıya sətirlərlə qarışıq nömrələr daxil etməyə və sonra onların cəmini hesablamağa çalışdı:
public class Main {

   public static void main(String[] args) {

       MyListClass list = new MyListClass();
       list.add(100);
       list.add(200);
       list.add("Lolkek");
       list.add("Shalala");

       Integer sum1 = (Integer) list.getData()[0] + (Integer) list.getData()[1];
       System.out.println(sum1);

       Integer sum2 = (Integer) list.getData()[2] + (Integer) list.getData()[3];
       System.out.println(sum2);
   }
}
Konsol çıxışı: 300 "main" mövzuda istisna java.lang.ClassCastException: java.lang.String Main.main-də java.lang.Integer-ə ötürülə bilməz(Main.java:14) Bu vəziyyətdə ən pis nədir? Proqramçının diqqətsizliyindən uzaqdır. Ən pisi odur ki, səhv kod proqramımızda vacib bir yerə düşdü və uğurla tərtib edildi . İndi səhvi kodlaşdırma mərhələsində deyil, yalnız sınaq mərhələsində görəcəyik (və bu ən yaxşı vəziyyətdədir!). İnkişaf zamanı səhvləri düzəltmək daha baha başa gəlir - həm pul, həm də vaxt. Bu, generiklərin üstünlüyüdür: ümumi sinif uğursuz proqramçıya səhvi dərhal aşkar etməyə imkan verəcək. Kod sadəcə tərtib edilməyəcək!
import java.util.ArrayList;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<Integer> myList1 = new ArrayList<>();

       myList1.add(100);
       myList1.add(100);
       myList1.add("Lolkek");//error!
       myList1.add("Shalala");//error!
   }
}
Proqramçı dərhal "ağlına gələcək" və dərhal özünü düzəldəcək. ListYeri gəlmişkən, bu cür səhvləri görmək üçün öz sinfimizi yaratmalı deyildik . Sadəcə olaraq növ mötərizələrini ( <Integer>) adi ArrayList-dən çıxarın!
import java.util.ArrayList;
import java.util.List;

public class Main {

   public static void main(String[] args) {

      List list = new ArrayList();

      list.add(100);
      list.add(200);
      list.add("Lolkek");
      list.add("Shalala");

       System.out.println((Integer) list.get(0) + (Integer) list.get(1));
       System.out.println((Integer) list.get(2) + (Integer) list.get(3));
   }
}
Konsol çıxışı: 300 İstisna "main" mövzuda java.lang.ClassCastException: java.lang.String Main.main(Main.java:16)-da java.lang.Integer-ə ötürülə bilməz , yəni "doğma" alətlərdən istifadə etməklə belə Java, siz bu səhvi edə və təhlükəli kolleksiya yarada bilərsiniz. Bununla belə, bu kodu IDEa-ya yerləşdirsək, biz bir xəbərdarlıq görürük: “ Java.util.List-in xam növünün üzvü kimi (E) əlavə etmək üçün yoxlanılmamış çağırış ” Bu, bizə element əlavə edərkən nəyinsə səhv ola biləcəyini bildirir. generics olmadan kolleksiya bu şəkildə deyil. Bəs “xam tip” ifadəsi nə deməkdir? Hərfi tərcümə olduqca dəqiq olacaq - “ xam tip ” və ya “ çirkli tip ”. Raw typetipinin çıxarıldığı ümumi sinifdir. Başqa sözlə, List myList1bu Raw type. Bunun əksi tip spesifikasiyası ilə düzgün yaradılmış ümumi raw typesinifdir generic type(sinf kimi də tanınır ). parameterized typeMisal üçün, List<String> myList1. Sualınız ola bilər: niyə istifadə etməyə icazə verilir raw types? Səbəbi sadədir. raw typesJava yaradıcıları uyğunluq problemləri yaratmamaq üçün dildə dəstəyi buraxdılar . Java 5.0 buraxılan zaman (generiklər ilk dəfə bu versiyada peyda oldu) istifadə edərək çoxlu kod artıq yazılmışdı raw types. Ona görə də bu ehtimal bu gün də mövcuddur. Biz artıq mühazirələrdə Coşua Blokun klassik “Effektiv Java” kitabından bir neçə dəfə bəhs etmişik. O, dilin yaradıcılarından biri kimi kitabda istifadə raw typesvə istifadə mövzusunu da diqqətdən kənarda qoymayıb generic types. Java-da generiklər nədir - 2Bu kitabın 23-cü fəslinin çox bəlağətli adı var: “Yeni kodda xam növlərdən istifadə etməyin.” Bu, yadda saxlamağınız lazım olan bir şeydir. Ümumi siniflərdən istifadə edərkən onları heç generic typevaxt raw type.

Tipli üsullar

Java ümumi metodlar yaradaraq fərdi metodları yazmağa imkan verir. Niyə belə üsullar əlverişlidir? Hər şeydən əvvəl ona görə ki, onlar müxtəlif növ parametrlərlə işləməyə imkan verirlər. Eyni məntiqi müxtəlif növlərə təhlükəsiz şəkildə tətbiq etmək olarsa, ümumi metod əla bir həlldir. Bir nümunəyə baxaq. Tutaq ki, bir növ siyahımız var myList1. Ondan bütün dəyərləri silmək və bütün boş yerləri yeni dəyərlə doldurmaq istəyirik. Ümumi metodlu sinifimiz belə görünəcək:
public class TestClass {

   public static <T> void fill(List<T> list, T val) {
       for (int i = 0; i < list.size(); i++)
           list.set(i, val);
   }

   public static void main(String[] args) {

       List<String> strings = new ArrayList<>();
       strings.add("Старая строка 1");
       strings.add("Старая строка 2");
       strings.add("Старая строка 3");

       fill(strings, "Новая строка");

       System.out.println(strings);

       List<Integer> numbers = new ArrayList<>();
       numbers.add(1);
       numbers.add(2);
       numbers.add(3);

       fill(numbers, 888);
       System.out.println(numbers);
   }
}
Sintaksisə diqqət yetirin, bir az qeyri-adi görünür:
public static <T> void fill(List<T> list, T val)
Qaytarma növündən əvvəl ümumi metodu göstərən <T> işarəsi qoyulur. Bu halda metod giriş kimi 2 parametr qəbul edir: obyektlərin siyahısı T və başqa ayrıca obyekt T. <T>-dən istifadə etməklə metodun yazılmasına nail olunur: biz sətirlərin siyahısını və rəqəmi ora ötürə bilmirik. Sətirlərin və sətirlərin siyahısı, nömrələrin və nömrələrin siyahısı, obyektlərimizin siyahısı Catvə başqa bir obyekt Cat- yeganə yol budur. Metod main()aydın şəkildə nümayiş etdirir ki, metod fill()müxtəlif növ məlumatlarla asanlıqla işləyir. Birincisi, o, giriş kimi sətirlərin və sətirlərin siyahısını, sonra isə nömrələrin və nömrələrin siyahısını alır. Konsol çıxışı: [Newline, Newline, Newline] [888, 888, 888] Təsəvvür edin ki fill(), 30 müxtəlif sinif üçün metod məntiqinə ehtiyacımız olub və ümumi metodlarımız yox idi. Fərqli məlumat növləri üçün eyni metodu 30 dəfə yazmaq məcburiyyətində qalacağıq! Lakin ümumi metodlar sayəsində kodumuzdan təkrar istifadə edə bilərik! :)

Yazılan siniflər

Siz yalnız Java-da təqdim olunan ümumi siniflərdən istifadə etməklə yanaşı, öz siniflərinizi də yarada bilərsiniz! Budur sadə bir nümunə:
public class Box<T> {

   private T t;

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

   public T get() {
       return t;
   }

   public static void main(String[] args) {

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

       stringBox.set("Старая строка");
       System.out.println(stringBox.get());
       stringBox.set("Новая строка");

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

       stringBox.set(12345);//ошибка компиляции!
   }
}
Sinifimiz Box<T>(“qutu”) çap olunur. Yaradılma zamanı ona məlumat tipi ( ) təyin etdikdən sonra <T>biz daha ona başqa növ obyektləri yerləşdirə bilməyəcəyik. Bunu misalda görmək olar. Yaradarkən obyektimizin sətirlərlə işləyəcəyini qeyd etdik:
Box<String> stringBox = new Box<>();
Və kodun son sətirində 12345 rəqəmini qutunun içərisinə qoymağa çalışdığımız zaman tərtib xətası alırıq! Eynilə, biz öz ümumi sinifimizi yaratdıq! :) Bununla bugünkü mühazirəmiz yekunlaşır. Ancaq biz generiklərlə vidalaşmırıq! Növbəti mühazirələrdə daha təkmil funksiyalar haqqında danışacağıq, ona görə də vidalaşmayın! ) Təhsilinizdə uğurlar! :)
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION