CodeGym /Blog Jawa /Acak /Generik ing Jawa
John Squirrels
tingkat
San Francisco

Generik ing Jawa

Diterbitake ing grup
Hi! Kita bakal ngomong babagan Java Generics. Aku kudu ngomong yen sampeyan bakal sinau akeh! Ora mung pelajaran iki, nanging uga sawetara pelajaran sabanjure, bakal dikhususake kanggo generik. Dadi, yen sampeyan kasengsem ing obat generik, dina iki sampeyan bakal seneng banget: sampeyan bakal sinau akeh babagan fitur generik. Lan yen ora, mundur lan santai! :) Iki topik penting banget, lan sampeyan kudu ngerti. Ayo diwiwiti kanthi prasaja: "apa" lan "kenapa".

Apa Generik Jawa?

Generik minangka jinis sing duwe parameter. Nalika nggawe jinis umum, sampeyan nemtokake ora mung jinis, nanging uga jinis data sing bakal bisa digunakake. Aku ngira conto sing paling jelas wis ana ing pikiran sampeyan: ArrayList! Iki carane kita biasane nggawe siji 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");
   }
}
Kaya sing sampeyan duga, fitur dhaptar iki yaiku kita ora bisa nglebokake kabeh: kerjane khusus karo obyek String . Saiki ayo njupuk digression sethitik menyang sajarah Jawa lan nyoba kanggo njawab pitakonan "kenapa?" Kanggo nindakake iki, kita bakal nulis versi sederhana saka kelas ArrayList. Dhaptar kita mung ngerti carane nambah data lan njupuk data saka array internal:

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;
   }
}
Upaminipun kita pengin dhaftar kita mung nyimpen Integer s. Kita ora nggunakake jinis umum. Kita ora pengin nyakup "instanceof Integer " sing jelas ing metode add () . Yen kita nindakake, kabeh kelas kita mung cocok kanggo Integer , lan kita kudu nulis kelas sing padha kanggo saben jinis data liyane ing donya! Kita bakal gumantung ing programer kita, lan mung ninggalake komentar ing kode kanggo mesthekake yen padha ora nambah apa kita ora pengin:

// Use this class ONLY with the Integer data type
public void add(Object o) {
   this.data[count] = o;
   count++;
}
Salah sawijining programer ora kejawab komentar iki lan ora sengaja nglebokake sawetara Strings ing dhaptar nomer 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 
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer 
      at Main.main (Main.java:14)
Apa sisih paling ala saka kahanan iki? Mesthi ora carelessness saka programmer. Sisih paling awon yaiku kode sing salah rampung ing papan sing penting ing program kita lan dikompilasi kanthi sukses. Saiki kita bakal nemoni bug kasebut ora nalika nulis kode, nanging mung sajrone nyoba (lan iki minangka skenario paling apik!). Ndandani kewan omo ing tahap pangembangan luwih akeh - saka segi dhuwit lan wektu. Iki persis ing ngendi generik entuk manfaat kanggo kita: kelas umum ngidini programmer sing ora beruntung ndeteksi kesalahan kasebut langsung. Program 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 langsung nyadari kesalahane lan langsung dadi luwih apik. Miturut cara, kita ora kudu nggawe kelas List dhewe kanggo ndeleng kesalahan iki. Cukup mbusak kurung sudut lan ketik ( <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 
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer 
     at Main.main(Main.java:16)
Ing tembung liyane, sanajan nggunakake mekanisme "native" Jawa, kita bisa nggawe kesalahan iki lan nggawe koleksi sing ora aman. Nanging, yen kita nempel kode iki menyang IDE, kita njaluk bebaya: "Panggilan sing ora dicenthang kanggo nambah (E) minangka anggota saka jinis mentah java.util.List" Kita dikandhani manawa ana sing salah nalika nambah item. menyang koleksi sing ora duwe jinis umum. Nanging apa tegese tembung "jinis mentah"? Jinis mentah yaiku kelas umum sing jinise wis dibusak. Ing tembung liyane, List myList1 minangka jinis mentah . Kosok baline saka jinis mentah yaiku jinis umum - kelas umum kanthi indikasi jinis parameterisasi . Contone, List<String> myList1. Sampeyan bisa uga takon kenapa basa kasebut ngidini nggunakake jinis mentah ? Alesane prasaja. Pencipta Jawa ninggalake dhukungan kanggo jinis mentah ing basa kasebut supaya ora nggawe masalah kompatibilitas. Nalika Java 5.0 dirilis (generik pisanan muncul ing versi iki), akeh kode sing wis ditulis nganggo jinis mentah . Akibaté, mekanisme iki isih didhukung nganti saiki. Kita wis bola-bali nyebutake buku klasik Joshua Bloch "Jawa Efektif" ing pawulangan. Minangka salah sawijining pangripta basa, dheweke ora ngliwati jinis mentah lan jinis generik ing bukune. Apa generik ing basa Jawa?  - 2Bab 23 buku kasebut nduweni judhul sing apik banget: "Aja nggunakake jinis mentah ing kode anyar" Iki sing kudu sampeyan eling. Nalika nggunakake kelas umum, aja ngowahi jinis umum dadi jinis mentah .

Metode umum

Jawa ngidini sampeyan nemtokake cara individu kanthi nggawe metode umum. Kepiye cara kasebut migunani? Ndhuwur kabeh, padha mbiyantu amarga ngidini sampeyan nggarap macem-macem jinis paramèter metode. Yen logika sing padha bisa ditrapake kanthi aman ing macem-macem jinis, cara umum bisa dadi solusi sing apik. Coba conto iki prasaja banget: Upaminipun kita duwe sawetara dhaftar disebut myList1 . Kita pengin mbusak kabeh nilai saka dhaptar lan isi kabeh spasi kosong karo nilai anyar. Mangkene tampilan kelas kita kanthi metode umum:

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("Old String 1");
       strings.add("Old String 2");
       strings.add("Old String 3");

       fill(strings, "New String");

       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é menyang sintaksis. Iku katon rada ora biasa:

public static <T> void fill(List<T> list, T val)
Kita nulis <T> sadurunge jinis bali. Iki nuduhake yen kita lagi nangani cara umum. Ing kasus iki, metode kasebut nampa 2 parameter minangka input: dhaptar obyek T lan obyek T liyane sing kapisah. Kanthi nggunakake <T>, kita nemtokake jinis parameter metode: kita ora bisa mlebu ing dhaptar Strings lan Integer. Dhaptar Strings lan String, dhaptar Integer lan Integer, dhaptar obyek Kucing lan obyek Kucing liyane - iku sing kudu kita lakoni. Cara utama () nggambaraké carane isi () cara bisa gampang digunakake kanggo karya karo macem-macem jinis data. Kaping pisanan, kita nggunakake metode kanthi dhaptar Strings lan String minangka input, banjur kanthi dhaptar Integer lan Integer. Output konsol:

[New String, New String, New String] [888, 888, 888]
Mbayangno yen kita ora duwe cara umum lan perlu logika isi () cara kanggo 30 kelas beda. Kita kudu nulis cara sing padha kaping 30 kanggo macem-macem jinis data! Nanging thanks kanggo cara umum, kita bisa nggunakake maneh kode kita! :)

Kelas umum

Sampeyan ora diwatesi karo kelas umum sing kasedhiya ing perpustakaan Jawa standar — sampeyan bisa 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("Old String");
       System.out.println(stringBox.get());
       stringBox.set("New String");

       System.out.println(stringBox.get());
      
       stringBox.set(12345); // Compilation error!
   }
}
Kelas Box<T> kita minangka kelas umum. Sawise nemtokake jinis data ( <T> ) sajrone nggawe, kita ora bisa nyelehake obyek saka jinis liyane ing njero. Iki bisa dideleng ing conto. Nalika nggawe obyek kita, kita nuduhake yen bakal bisa digunakake karo Strings:

Box<String> stringBox = new Box<>();
Lan ing baris pungkasan kode, nalika kita nyoba kanggo nyelehake nomer 12345 ing kothak, kita njaluk kesalahan kompilasi! Gampang banget! Kita wis nggawe kelas umum kita dhewe! :) Kanthi mekaten, wulangan dinten punika sampun rampung. Nanging kita ora ngucapake pamit kanggo generik! Ing pelajaran sabanjure, kita bakal ngomong babagan fitur sing luwih maju, mula aja lunga! ) Kanggo nguatake apa sing sampeyan sinau, disaranake sampeyan nonton video pelajaran saka Kursus Jawa
Sukses paling apik ing pasinaon! :)
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION