JavaRush /Blog Jawa /Random-JV /Apa generik ing Jawa

Apa generik ing Jawa

Diterbitake ing grup
Hello! Dina iki kita bakal ngomong babagan generik. Aku kudu ujar manawa sampeyan bakal sinau akeh perkara anyar! Ora mung iki, nanging uga sawetara ceramah sabanjure bakal dikhususake kanggo generik. Apa generik ing basa Jawa - 1 Mulane, yen topik iki menarik kanggo sampeyan, sampeyan beruntung: dina iki sampeyan bakal sinau akeh babagan fitur generik. Nah, yen ora, tenang lan santai! :) Iki topik penting banget lan sampeyan kudu ngerti. Ayo diwiwiti kanthi prasaja: "apa" lan "kenapa". Apa generik? Generik minangka jinis kanthi parameter. Nalika nggawe umum, sampeyan nemtokake ora mung jinis, nanging uga jinis data sing kudu digarap. Aku mikir conto sing paling jelas wis ana ing pikiran sampeyan - iki ArrayList! Mangkene carane biasane nggawe ing program:

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");
   }
}
Minangka sampeyan bisa guess, peculiarity saka dhaftar iku ora bakal bisa kanggo "masak" kabeh menyang: iku mung dianggo karo obyek String. Saiki ayo padha njelajah sejarah Jawa lan nyoba mangsuli pitakon: “kenapa?” Kanggo nindakake iki, kita dhewe bakal nulis versi sing disederhanakake saka kelas ArrayList. Dhaptar kita mung bisa nambah data menyang array internal lan nampa data iki:

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;
   }
}
Contone, kita pengin dhaptar mung nyimpen nomer Integer. Kita ora duwe generik. Kita ora bisa kanthi tegas nemtokake conto mriksa Integering add(). Banjur kabeh kelas kita mung cocok kanggo Integer, lan kita kudu nulis kelas sing padha kanggo kabeh jinis data sing ana ing donya! Kita mutusake kanggo ngandelake programer kita lan mung ninggalake komentar ing kode kasebut supaya ora nambah apa-apa sing ora perlu ing kana:

//use it ONLY with Integer data type
public void add(Object o) {
   this.data[count] = o;
   count++;
}
Salah sawijining programer ora kejawab komentar iki lan kanthi ora sengaja nyoba nglebokake nomer sing dicampur karo senar ing dhaptar, banjur ngitung jumlahe:

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);
   }
}
Output konsol: 300 Pengecualian ing thread "utama" java.lang.ClassCastException: java.lang.String ora bisa dibuwang menyang java.lang.Integer ing Main.main (Main.java: 14) Apa sing paling awon ing kahanan iki? Adoh saka kang inattentiveness programmer. Sing paling awon yaiku kode sing salah wis ana ing papan sing penting ing program kita lan sukses dikompilasi . Saiki kita bakal weruh kesalahan ora ing tahap coding, nanging mung ing tahap testing (lan iki paling apik!). Ndandani kewan omo mengko ing pembangunan biaya luwih akeh-loro dhuwit lan wektu. Iki sabenere kauntungan saka generik: kelas umum bakal ngidini programmer apes ndeteksi kesalahan langsung. Kode mung ora bakal kompilasi!

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!
   }
}
Programmer bakal langsung "sadar" lan langsung mbenerake awake dhewe. Miturut cara, kita ora kudu nggawe kelas kita dhewe Listkanggo ndeleng kesalahan iki. Cukup mbusak kurung jinis ( <Integer>) saka ArrayList biasa!

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));
   }
}
Output konsol: 300 Pengecualian ing thread "utama" java.lang.ClassCastException: java.lang.String ora bisa dibuwang menyang java.lang.Integer ing Main.main(Main.java:16) Yaiku, sanajan nggunakake alat "native" Jawa, sampeyan bisa nggawe kesalahan iki lan nggawe koleksi ora aman. Nanging, yen kita nempel kode iki menyang IDEa, kita ndeleng bebaya: " Telpon ora dicenthang kanggo nambah (E) minangka anggota saka jinis mentah java.util.List "Iki ngandhani yen ana sing salah nalika nambah unsur menyang a koleksi tanpa generik ora cara iki. Nanging apa tegese tembung "jinis mentah"? Terjemahan harfiah bakal cukup akurat - " jinis mentah " utawa " jinis reged ". Raw typepunika kelas umum saka kang jinis wis dibusak. Ing tembung liyane, List myList1iki Raw type. Kosok baline raw typeyaiku generic typekelas umum (uga dikenal minangka kelas parameterized type), digawe kanthi bener, kanthi spesifikasi jinis. Tuladhane, List<String> myList1. Sampeyan bisa uga duwe pitakonan: kok malah diijini nggunakake raw types? Alesane prasaja. Para pangripta Jawa ninggalaken panyengkuyung ing basa kasebut raw typessupaya ora nuwuhake masalah kompatibilitas. Nalika Java 5.0 dirilis (generik pisanan muncul ing versi iki), akeh kode sing wis ditulis nganggo raw types. Mulane, kemungkinan iki isih ana nganti saiki. Kita wis nyebutake buku klasik Joshua Bloch "Jawa Efektif" luwih saka sepisan ing ceramah. Minangka salah sawijining pangripta basa, dheweke ora nglirwakake topik nggunakake raw typeslan ing buku kasebut generic types. Apa generik ing basa Jawa - 2Bab 23 buku iki nduweni judhul sing apik banget: "Aja nggunakake jinis mentah ing kode anyar." Iki minangka perkara sing kudu sampeyan eling. Nalika nggunakake kelas umum, aja ngowahi generic typedadi raw type.

Metode Ketik

Jawa ngidini sampeyan ngetik cara individu, nggawe cara umum sing disebut. Apa sebabe cara-cara kasebut trep? Kaping pisanan, amarga ngidini sampeyan nggarap macem-macem jinis paramèter. Yen logika sing padha bisa ditrapake kanthi aman ing macem-macem jinis, cara umum minangka solusi sing apik. Ayo padha ndeleng conto. Ayo kita duwe sawetara jinis dhaptar myList1. Kita pengin mbusak kabeh nilai saka iku, lan isi kabeh spasi free karo nilai anyar. Iki kelas kita kanthi metode umum bakal katon kaya:

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);
   }
}
Pay manungsa waé kanggo sintaks, iku katon sethitik mboten umum:

public static <T> void fill(List<T> list, T val)
Jinis bali didhisiki <T>, sing nuduhake cara umum. Ing kasus iki, cara njupuk 2 paramèter minangka input: dhaptar obyek T lan obyek kapisah liyane T. Kanthi nggunakake <T>, ngetik cara wis ngrambah: kita ora bisa pass dhaftar strings lan nomer ana. Dhaptar senar lan senar, dhaptar nomer lan nomer, dhaptar obyek Catlan obyek liyane Cat- mung siji-sijine cara. Cara kasebut main()kanthi jelas nuduhake manawa metode kasebut fill()gampang dianggo karo macem-macem jinis data. Pisanan, iku njupuk minangka input dhaftar strings lan senar, lan banjur dhaptar nomer lan nomer. Output konsol: [Newline, Newline, Newline] [888, 888, 888] Bayangake yen fill()kita butuh logika metode kanggo 30 kelas sing beda, lan kita ora duwe metode umum. Kita bakal dipeksa nulis cara sing padha kaping 30, mung kanggo jinis data sing beda! Nanging thanks kanggo cara umum, kita bisa nggunakake maneh kode kita! :)

Kelas sing diketik

Sampeyan ora mung bisa nggunakake kelas umum sing kasedhiya ing Jawa, nanging uga nggawe dhewe! Punika conto prasaja:

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);//ошибка компиляции!
   }
}
Kelas kita Box<T>("kotak") diketik. Sawise menehi jinis data () sajrone nggawe <T>, kita ora bakal bisa nempatake obyek saka jinis liyane. Iki bisa dideleng ing conto. Nalika nggawe, kita nemtokake manawa obyek bakal bisa digunakake karo senar:

Box<String> stringBox = new Box<>();
Lan nalika ing baris pungkasan kode kita nyoba kanggo nyelehake nomer 12345 nang kothak, kita njaluk kesalahan kompilasi! Kaya ngono, kita nggawe kelas umum dhewe! :) Pungkasane ceramah kita dina iki. Nanging kita ora ngucapake pamit kanggo generik! Ing kuliah sabanjure kita bakal ngomong babagan fitur sing luwih maju, mula aja pamit! ) Sugeng sinau! :)
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION