KodeGym/Blog Jawa/Acak/Wildcards ing generik
John Squirrels
tingkat
San Francisco

Wildcards ing generik

Diterbitake ing grup
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 :) Wildcards ing generik - 1Ayo 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 Stringobyek menyang Objectobyek. 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 Stringobyek menyang Objectutawa 20 obyek? Ana bedane penting antarane obyek lan koleksi obyek . Yen Bkelas iku anak saka Akelas, banjur Collection<B>dudu anak saka Collection<A>. Iki kok kita padha ora bisa kanggo cast kita List<String>menyang aList<Object>. Stringiku 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 Objecting stringskoleksi kasebut! Mangkono, kita wis kelangan jaminan yen koleksi kita mung ngemot Stringobyek 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 Animalobyek utawa koleksi obyek saka sembarang kelas sing mudhun saka Animal(? ngluwihi Animal). Ing tembung liyane, cara bisa nampa koleksi Animal, Pet, Dog, utawa Catobyek — 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 Petkelas ing ngisor, lan kelas Catlan Doging 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 Catobyek utawa leluhur kelas Catminangka input. Ing kasus iki, Catkelas, wong tuwane Pet, lan wong tuwane, Animalkabeh cocog karo katrangan iki. Kelas kasebut Dogora 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! :)
Komentar
  • Popular
  • Anyar
  • lawas
Sampeyan kudu mlebu kanggo ninggalake komentar
Kaca iki durung duwe komentar