Generics
Subtopik Generics
Intro to generics
Generic Programming
Generics dan subtipe
Wildcard ?
Intro
Pada Java rilis 5.0, terjadi banyak penambahan
pada bahasa Java.
Selain dari annotation, penambahan yang penting
lainnya adalah generics
Jika anda melihat ada simbol seperti <E> atau <T>
maka itu menandakan bagian yang diberi simbol adalah generics
Why Generics?
// Anggap anda ingin membuat koleksi String dalam Vector. // Tak sengaja, anda memasukkan unsur Integer ke
// dalamnya. Compiler tidak akan mendeteksi hal ini. // Coding tersebut tidak type safe.
Vector v = new Vector();
v.add(new String(“valid string”)); // sengaja
Why Generics?
Masalah: tipe data unsur pada Collection
Compiler tidak bisa memverifikasi tipe data unsur pada Collection
Proses assignment memerlukan type casting
Dapat memunculkan ClassCastException saat runtime
Solusi: Generics
Beritahu compiler tipe data collection
Biarkan compiler yang melakukan casting
Compiler akan mengecek apakah anda memasukkan data yang benar jika tidak muncul error type mismatch
Contoh penggunaan generics
Buat class collection namun menspesifikkan tipe
datanya.
Sejak J2SE 5.0, semua class collection ditulis ulang
menjadi bentuk generics.
// Buat Vector dgn tipe data String
Vector<String> vs = new Vector<String>();
vs.add(new Integer(5)); // Error terdeteksi saat // kompilasi
vs.add(new String(“hello”));
Contoh penggunaan generics (2)
Class generics bisa punya beberapa parameter
Tipe data parameter bisa berupa class buatan
sendiri
// HashMap dgn 2 parameter
HashMap<String, Mammal> map =
new HashMap<String, Mammal>();
map.put(“mouse”, new Mammal(“mouse")); Mammal w = map.get(“mouse”);
What is generics?
Generics menyediakan abstraksi pada tipe data
Generics membuat coding menjadi type safe
Atau tidak ada masalah pada tipe data
Generic programming
Coding yang dapat digunakan oleh beberapa objek
yang tipenya berlainan.
Andai kita memiliki class KoleksiString,
KoleksiInteger, KoleksiDouble.
Dengan menggunakan generic programming, kita
dapat membuat class Koleksi yang dapat
Contoh sebelum generic
public class KoleksiString { private String data;
public String getData() { return data;
}
public void setData(String data) { this.data = data;
} }
Contoh sebelum generic
public class KoleksiInteger { private int data;
public int getData() { return data;
}
public void setData(int data) { this.data = data;
} }
Contoh sebelum generic
public class KoleksiDouble { private double data;
public double getData() { return data;
}
public void setData(double data) { this.data = data;
} }
Generic code buatan sendiri
3 coding koleksi tadi cukup melelahkan jika
dilakukan, apalagi kalau ingin menambah koleksi baru
Maka gunakan generic untuk mengatasi masalah
tersebut dengan hanya membuat satu class koleksi yang generic
Contoh generic buatan sendiri
public class Koleksi<T> { private T data;
public T getData() { return data; }
public void setData(T data) { this.data = data;
} }
Generic ditandai dengan tanda < >. Pada kode di atas berarti kita
membuat generic dengan simbol T, sehingga T dianggap sebagai tipe data dalam lingkup class tersebut. Sewaktu class Koleksi dipakai, T diganti menjadi tipe data tertentu.
Type Parameter
Beberapa type parameter yang umum digunakan
pada generic: T – Type E – Element K – Key N – Number V – Value
Tidak bisa tipe data primitif
Generic hanya dapat menggunakan Object.
Sehingga tipe data primitif harus diubah ke bentuk classnya
Contoh: int menjadi Integer
public class Main {
public static void main(String[] args) {
Koleksi<String> a = new Koleksi<String>(); a.setData("String");
Koleksi<Integer> b = new Koleksi<Integer>(); b.setData(1);
} }
Contoh lain generic buatan sendiri
public class Pair<F, S> { F first; S second;
public Pair(F f, S s) {
first = f; second = s; }
public void setFirst(F f){ first = f;
}
public F getFirst(){ return first; }
public void setSecond(S s){ second = s;
Pemakaiannya
public class MyOwnGenericClass {
public static void main(String[] args) { // Buat objek Pair <F, S>
Number n1 = new Integer(5); String s1 = new String("Sun");
Pair<Number,String> p1 = new Pair<Number,String>(n1, s1);
System.out.println(“nilai pertama p1 (pada awalnya) = " + p1.getFirst());
System.out.println("nilai kedua p1 (pada awalnya) = " + p1.getSecond());
// Set internal variables of p1. p1.setFirst(new Long(6L));
p1.setSecond(new String("rises"));
System.out.println("nilai pertama p1 (setelah diubah) = " + p1.getFirst());
System.out.println("nilai kedua p1 (setelah diubah) = " + p1.getSecond());
Method generic
Generic juga dapat dipakai pada method.
Cara: simbol generic dideklarasi sebelum return
value
public <T> T ambilTengah(T[] data)
public <T> void kosongkan(T[] data)
public class Utilitas {
public static <T> T ambilTengah(T[] data) { return data[data.length / 2];
} }
Method generic (2)
Pada method generic, simbol hanya berlaku pada
method itu saja dan tidak berlaku pada method lain dalam class
public class Utilitas {
public <T> T ambilTengah(T[] data) { return data[data.length / 2]; }
// simbol T tidak dikenal
public T ambilAwal(T[] data){ return data[0];
} }
Pewarisan pada generic
Pewarisan/inheritance juga berlaku pada generic
Berguna untuk membatasi input data yang dapat digunakan
Defaultnya generic simbol merupakan turunan class Object
Contoh pewarisan pada generic
public class Musisi {
public void nyanyi() { // nyanyi } } public class MusisiBerbakat extends Musisi{
public void dansa() { // dansa
} }
public class Koleksi <T extends Musisi> {
private T data;
public T getData() { return data;
}
public void setData(T data) {
this.data = data; }
}
Pada contoh ini, class Koleksi hanya dapat digunakan oleh class Musisi dan turunannya
Contoh pewarisan pada generic
public class Koleksi <T extends Musisi> {
private T data;
public T getData() { return data;
}
public void setData(T data) {
this.data = data; }
public void nyanyiEuy(){ if(this.data != null){
this.data.nyanyi();
} }
}
Jika kita mengkhususkan
generic untuk class
tertentu, maka method class tersebut pun dapat dipanggil
Jika tidak, maka hanya
method dari class Object saja yang dikenal
Generic pada interface
Selain class dan method, interface juga dapat dibuat
Generics dan subtipe
Anda dapat melakukan ini:
Object o = new Integer(5);
Anda juga dapat melakukan ini:
Object[] or = new Integer[5];
Apakah anda dapat melakukan ini?
Generics dan subtipe
Kenapa bisa jadi error kompilasi?
Andai hal tersebut dibolehkan, maka ClassCastException dapat muncul sewaktu runtime. Jadi apa gunanya
generics?
Jadi tidak ada relasi pewarisan antara tipe data
Generics dan subtipe
Namun coding berikut tidak masalah
Relasi pewarisan/inheritance antar sesama class
Generics dan subtipe
Perhatikan coding berikut
Unsur yang dimasukkan dalam collection akan tetap
Why wildcard ?
Anggap ada coding untuk mencetak semua unsur
Apa masalahnya
Solusi: dengan wildcard ?
Gunakan wildcard <?> sebagai argumen
Collection <?> bermakna collection yang tidak
diketahui tipe datanya
Mengakses unsur collection yang tidak diketahui tipe
Tapi…
Anda tidak dapat mengakses unsur collection yang
tidak diketahui tipe datanya menggunakan selain dari tipe data Object
Karena masih ?
Kita tidak dapat menambah unsur ke dalam
Bounded wildcard
Jika anda ingin mengkhususkan tipe data yang tidak
diketahui menjadi subtipe dari tipe data tertentu, gunakan bounded wildcard
Raw type
Class bertipe generic masih bisa di-instantiasi
(penciptaan objek) tanpa menggunakan argumen
Jadi coding sebelum J2SE 5.0 masih dapat
Type erasure
Compiler bertanggungjawab untuk “memahami”
generics pada saat kompilasi.
Namun compiler juga bertanggungjawab untuk
menghapus “pemahaman” mengenai class generic, hal ini disebut type erasure.
Informasi tipe data pada generic dihapus dari
byte-code setelah kompilasi.
Jadi generic-nya tidak wujud lagi pada saat runtime
Setelah kompilasi, semua saling berbagi class yang
sama
Contoh class yang menggunakan ArrayList<String>, ArrayList<Integer> akan sama dengan class ArrayList
True or False?
ArrayList<Integer> ai = new ArrayList<Integer>(); ArrayList<String> as = new ArrayList<String>(); Boolean b1 = (ai.getClass() == as.getClass()); System.out.println("Do ArrayList<Integer> and
Type-safe code
Compiler memastikan:
Bytecode menjadi type-correct saat runtime
Atau compiler memberikan warning (menggunakan raw type) saat kompilasi
Jika suatu coding dikompilasi tanpa warning dan
tidak memiliki casting maka program tersebut tidak akan memunculkan ClassCastException saat
runtime