Hi! Ayo kita nerusake sinau babagan generik. Sampeyan wis entuk akeh kawruh babagan pelajaran sadurunge (babagan nggunakake varargs nalika nggarap generik lan babagan erasure jinis ), nanging ana topik penting sing durung dianggep - wildcards . Iki minangka fitur generik sing penting banget. Dadi luwih supaya kita wis darmabakti pawulangan kapisah kanggo iku! Sing jarene, ora ana sing rumit babagan wildcard. Sampeyan bakal weruh langsung :)
Ayo ndeleng conto:

public class Main {
public static void main(String[] args) {
String str = new String("Test!");
// No problem
Object obj = str;
List<String> strings = new ArrayList<String>();
// Compilation error!
List<Object> objects = strings;
}
}
Apa sing kedadeyan ing kene? Kita ndeleng rong kahanan sing padha. Ing kasus kasebut, kita mbuwang String
obyek menyang Object
obyek. Ora ana masalah ing kene - kabeh bisa digunakake kaya sing dikarepake. Nanging ing kahanan kapindho, compiler ngasilake kesalahan. Nanging kita uga nindakake perkara sing padha, ta? Wektu iki kita mung nggunakake koleksi sawetara obyek. Nanging kenapa kesalahan kasebut kedadeyan? Apa bedane? Apa kita ngirim siji String
obyek menyang Object
utawa 20 obyek? Ana bedane penting antarane obyek lan koleksi obyek . Yen B
kelas iku anak saka A
kelas, banjur Collection<B>
dudu anak saka Collection<A>
. Iki kok kita padha ora bisa kanggo cast kita List<String>
menyang aList<Object>
. String
iku anak saka Object
, nanging List<String>
dudu anak saka List<Object>
. Iki bisa uga ora katon super intuisi. Kenging punapa pangripta basa menika damel kados makaten? Ayo bayangake manawa kompiler ora menehi kesalahan:
List<String> strings = new ArrayList<String>();
List<Object> objects = strings;
Ing kasus iki, kita bisa, contone, nindakake ing ngisor iki:
objects.add(new Object());
String s = strings.get(0);
Amarga kompiler ora menehi kesalahan lan ngidini kita nggawe List<Object>
referensi sing nuduhake strings
, kita bisa nambah obyek lawas Object
ing strings
koleksi kasebut! Mangkono, kita wis kelangan jaminan yen koleksi kita mung ngemot String
obyek sing ditemtokake dening argumen tipe ing invocation tipe umum . Ing tembung liyane, kita wis ilang kauntungan utama generik - jinis safety. Lan amarga compiler ora mungkasi kita nindakake iki, kita bakal entuk kesalahan mung ing wektu mbukak, sing tansah luwih elek tinimbang kesalahan kompilasi. Kanggo nyegah kahanan kaya iki, kompiler menehi kesalahan:
// Compilation error
List<Object> objects = strings;
...lan ngelingake yen List<String>
dudu keturunan List<Object>
. Iki minangka aturan ironclad kanggo generik, lan kudu eling nalika nggarap. Ayo nerusake. Upaminipun kita duwe hierarki kelas cilik:
public class Animal {
public void feed() {
System.out.println("Animal.feed()");
}
}
public class Pet extends Animal {
public void call() {
System.out.println("Pet.call()");
}
}
public class Cat extends Pet {
public void meow() {
System.out.println("Cat.meow()");
}
}
Hierarki iki paling ndhuwur dening kelas Animal prasaja, kang dipun warisaken dening Pet. Pet duwe 2 subclass: Dog lan Cat. Saiki umpamane kita kudu nggawe iterateAnimals()
cara sing gampang. Cara kasebut kudu njupuk koleksi kewan apa wae ( Animal
, Pet
, Cat
, Dog
), ngulang kabeh unsur, lan nampilake pesen ing konsol sajrone saben pengulangan. Ayo nyoba nulis cara kaya mangkene:
public static void iterateAnimals(Collection<Animal> animals) {
for(Animal animal: animals) {
System.out.println("Another iteration in the loop!");
}
}
Iku misale jek sing masalah wis ditanggulangi! Nanging, kaya sing bubar sinau, List<Cat>
, List<Dog>
lan List<Pet>
dudu keturunan List<Animal>
! Iki tegese yen kita nyoba nelpon iterateAnimals()
metode kasebut kanthi dhaptar kucing, kita entuk kesalahan kompilasi:
import java.util.*;
public class Main3 {
public static void iterateAnimals(Collection<Animal> animals) {
for(Animal animal: animals) {
System.out.println("Another iteration in the loop!");
}
}
public static void main(String[] args) {
List<Cat> cats = new ArrayList<>();
cats.add(new Cat());
cats.add(new Cat());
cats.add(new Cat());
cats.add(new Cat());
// Compilation error!
iterateAnimals(cats);
}
}
Kahanan kasebut ora katon apik kanggo kita! Apa kita kudu nulis cara sing kapisah kanggo ngitung saben jinis kewan? Bener, ora, kita ora :) Lan kaya mengkono, wildcards mbantu kita karo iki! Kita bisa ngatasi masalah kanthi cara sing gampang nggunakake konstruksi ing ngisor iki:
public static void iterateAnimals(Collection<? extends Animal> animals) {
for(Animal animal: animals) {
System.out.println("Another iteration in the loop!");
}
}
Iki minangka wildcard. Luwih tepate, iki pisanan saka sawetara jinis wildcards. Iki dikenal minangka wildcards ndhuwur-wates lan ditulis dening ? ngluwihi . Apa sing diarani konstruksi iki? Iki tegese cara nampa koleksi Animal
obyek utawa koleksi obyek saka sembarang kelas sing mudhun saka Animal
(? ngluwihi Animal). Ing tembung liyane, cara bisa nampa koleksi Animal
, Pet
, Dog
, utawa Cat
obyek — iku ndadekake ora prabédan. Ayo gawe uwong yakin yen bisa:
public static void main(String[] args) {
List<Animal> animals = new ArrayList<>();
animals.add(new Animal());
animals.add(new Animal());
List<Pet> pets = new ArrayList<>();
pets.add(new Pet());
pets.add(new Pet());
List<Cat> cats = new ArrayList<>();
cats.add(new Cat());
cats.add(new Cat());
List<Dog> dogs = new ArrayList<>();
dogs.add(new Dog());
dogs.add(new Dog());
iterateAnimals(animals);
iterateAnimals(pets);
iterateAnimals(cats);
iterateAnimals(dogs);
}
Output konsol:
Another iteration in the loop!
Another iteration in the loop!
Another iteration in the loop!
Another iteration in the loop!
Another iteration in the loop!
Another iteration in the loop!
Another iteration in the loop!
Another iteration in the loop!
We digawe total 4 koleksi lan 8 obyek, lan ana persis 8 entri ing console. Kabeh kerjane apik! :) Wildcard ngidini kita gampang pas logika perlu disambungake kanggo jinis tartamtu menyang cara siji. Kita ngilangi kebutuhan kanggo nulis cara sing kapisah kanggo saben jinis kewan. Bayangake carane akeh cara sing bakal dibutuhake yen aplikasi kita digunakake dening kebon binatang utawa kantor Veterinary :) Nanging saiki ayo goleki kahanan sing beda. Hierarki warisan kita tetep ora owah: kelas paling dhuwur yaiku Animal
, kanthi Pet
kelas ing ngisor, lan kelas Cat
lan Dog
ing tingkat sabanjure. Saiki sampeyan kudu nulis ulang iterateAnimals()
cara supaya bisa digunakake karo sembarang jinis kewan, kajaba asu . Yaiku, kudu nampa Collection<Animal>
,Collection<Pet>
utawa Collection<Car>
, nanging ngirim ora bisa karo Collection<Dog>
. Kepiye carane bisa nggayuh iki? Iku misale jek sing maneh ngadhepi prospek nulis cara kapisah kanggo saben jinis: / Carane liya kita nerangake kanggo compiler apa kita arep kelakon? Iku bener cukup prasaja! Sawise maneh, wildcards teka kanggo mbantu kita ing kene. Nanging wektu iki kita bakal nggunakake jinis wildcard liyane - wildcard wates ngisor , kang ditulis nggunakake super .
public static void iterateAnimals(Collection<? super Cat> animals) {
for(int i = 0; i < animals.size(); i++) {
System.out.println("Another iteration in the loop!");
}
}
Ing kene prinsip padha. Konstruksi <? super Cat>
ngandhani kompiler yen iterateAnimals()
metode kasebut bisa ditampa minangka input koleksi Cat
obyek utawa leluhur kelas Cat
minangka input. Ing kasus iki, Cat
kelas, wong tuwane Pet
, lan wong tuwane, Animal
kabeh cocog karo katrangan iki. Kelas kasebut Dog
ora cocog karo watesan kita, mula nyoba nggunakake metode kanthi List<Dog>
argumen bakal nyebabake kesalahan kompilasi:
public static void main(String[] args) {
List<Animal> animals = new ArrayList<>();
animals.add(new Animal());
animals.add(new Animal());
List<Pet> pets = new ArrayList<>();
pets.add(new Pet());
pets.add(new Pet());
List<Cat> cats = new ArrayList<>();
cats.add(new Cat());
cats.add(new Cat());
List<Dog> dogs = new ArrayList<>();
dogs.add(new Dog());
dogs.add(new Dog());
iterateAnimals(animals);
iterateAnimals(pets);
iterateAnimals(cats);
// Compilation error!
iterateAnimals(dogs);
}
Kita wis ngrampungake masalah kita, lan wildcards maneh dadi migunani banget :) Kanthi iki, pelajaran wis rampung. Saiki sampeyan ngerti sepira pentinge generik ing sinau babagan basa Jawa — kita wis entuk 4 pelajaran kabeh babagan iki! Nanging saiki sampeyan wis ngerti topik kasebut lan sampeyan bisa mbuktekake katrampilan sampeyan ing wawancara kerja :) Lan saiki, wektune bali menyang tugas! Sukses paling apik ing pasinaon! :)
GO TO FULL VERSION