JavaRush /Blog Jawa /Random-JV /Wildcards ing Java Generics

Wildcards ing Java Generics

Diterbitake ing grup
Hello! Kita terus sinau topik generik. Sampeyan wis duwe jumlah apik saka kawruh bab mau saka ceramah sadurungé (babagan nggunakake varargs nalika nggarap generik lan bab jinis erasure ), nanging kita durung nutupi siji topik penting: wildcards . Iki minangka fitur generik sing penting banget. Dadi luwih supaya kita wis darmabakti kuliah kapisah kanggo iku! Nanging, ora ana sing rumit babagan wildcard, sampeyan bakal weruh saiki :) Wildcards ing generik - 1Ayo goleki conto:
public class Main {

   public static void main(String[] args) {

       String str = new String("Test!");
       // ниHowих проблем
       Object obj = str;

       List<String> strings = new ArrayList<String>();
       // ошибка компиляции!
       List<Object> objects = strings;
   }
}
Apa sing kedadeyan ing kene? Kita ndeleng rong kahanan sing padha. Ing kawitan iki, kita nyoba kanggo matak obyek Stringkanggo ngetik Object. Ora ana masalah karo iki, kabeh bisa digunakake. Nanging ing kahanan kapindho, compiler mbuwang kesalahan. Sanajan katon yen kita nindakake perkara sing padha. Mung saiki kita nggunakake koleksi sawetara obyek. Nanging kenapa kesalahan kasebut kedadeyan? Apa prabédan, ateges, apa kita matak siji obyek Stringkanggo jinis Objectutawa 20 obyek? Ana prabédan penting antarane obyek lan koleksi obyek . Yen kelas minangka penerus kelas , mula ora dadi penerus . Mulane kita ora bisa nggawa kita menyang . iku ahli waris , nanging dudu ahli waris . Secara intuisi, iki ora katon logis banget. Apa sebabe para pangripta basa dipandu dening prinsip iki? Ayo bayangake manawa kompiler ora bakal menehi kesalahan ing kene: BАCollection<B>Collection<A>List<String>List<Object>StringObjectList<String>List<Object>
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);
Wiwit kompiler ora menehi kesalahan lan ngidini kita nggawe referensi List<Object> objectkanggo koleksi strings strings, kita stringsora bisa nambah senar, nanging mung obyek apa wae Object! Dadi, kita wis kelangan jaminan manawa mung obyek sing ditemtokake ing umum sing ana ing koleksi kitaString . Sing, kita wis ilang kauntungan utama generik - jinis safety. Lan wiwit kompiler ngidini kita nindakake kabeh iki, tegese kita mung bakal entuk kesalahan sajrone eksekusi program, sing mesthi luwih elek tinimbang kesalahan kompilasi. Kanggo nyegah kahanan kasebut, kompiler menehi kesalahan:
// ошибка компиляции
List<Object> objects = strings;
...lan ngelingake yen List<String>dheweke dudu ahli waris List<Object>. Iki minangka aturan ironclad kanggo operasi generik, lan kudu eling nalika nggunakake. Ayo nerusake. Ayo 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()");
   }
}
Ing sirah saka hirarki mung Animals: Pets dipun warisaken saka wong-wong mau. Pets dipérang dadi 2 jinis - asu lan kucing. Saiki bayangake yen kita kudu nggawe cara sing prasaja iterateAnimals(). Cara kasebut kudu nampa koleksi kewan apa wae ( Animal, Pet, Cat, Dog), iterate liwat kabeh unsur, lan output soko kanggo console saben wektu. Ayo nyoba nulis metode iki:
public static void iterateAnimals(Collection<Animal> animals) {

   for(Animal animal: animals) {

       System.out.println("Еще один шаг в цикле пройден!");
   }
}
Iku bakal katon yen masalah wis ditanggulangi! Nanging, kaya sing bubar ditemokake, List<Cat>, List<Dog>utawa List<Pet>dudu ahli waris List<Animal>! Mulane, nalika nyoba nelpon cara iterateAnimals()karo dhaptar kucing, kita bakal nampa kesalahan compiler:
import java.util.*;

public class Main3 {


   public static void iterateAnimals(Collection<Animal> animals) {

       for(Animal animal: animals) {

           System.out.println("Еще один шаг в цикле пройден!");
       }
   }

   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());

       //ошибка компилятора!
       iterateAnimals(cats);
   }
}
Kahanan ora katon apik kanggo kita! Pranyata metu sing kita kudu nulis cara kapisah kanggo enumerating kabeh jinis kewan? Bener, ora, sampeyan ora kudu :) Lan wildcard bakal mbantu kita ! Kita bakal ngatasi masalah kasebut kanthi cara sing gampang, nggunakake konstruksi ing ngisor iki:
public static void iterateAnimals(Collection<? extends Animal> animals) {

   for(Animal animal: animals) {

       System.out.println("Еще один шаг в цикле пройден!");
   }
}
Iki minangka wildcard. Luwih tepate, iki pisanan saka sawetara jinis wildcard - " ngluwihi " (jeneng liya Upper Bounded Wildcards ). Apa desain iki marang kita? Iki tegese cara njupuk minangka input koleksi obyek kelas Animalutawa obyek saka sembarang kelas turunan Animal (? extends Animal). AnimalIng tembung liyane, cara bisa nampa koleksi , Pet, Dogutawa minangka input Cat- ora ana bedane. Ayo priksa manawa iki bisa digunakake:
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:

Еще один шаг в цикле пройден!
Еще один шаг в цикле пройден!
Еще один шаг в цикле пройден!
Еще один шаг в цикле пройден!
Еще один шаг в цикле пройден!
Еще один шаг в цикле пройден!
Еще один шаг в цикле пройден!
Еще один шаг в цикле пройден!
Kita wis nggawe total 4 koleksi lan 8 obyek, lan ana persis 8 entri ing console. Kabeh kerjane apik! :) Wildcard diijini kita gampang pas karo logika perlu karo naleni kanggo jinis tartamtu menyang siji cara. Kita nyingkirake kudu nulis cara sing kapisah kanggo saben jinis kewan. Bayangake carane akeh cara sing bakal ditindakake yen aplikasi kita digunakake ing kebon binatang utawa klinik Veterinary :) Saiki ayo goleki kahanan sing beda. Hierarki warisan kita bakal tetep padha: kelas ndhuwur-tingkat punika Animal, mung ngisor kelas Pets Pet, lan ing tingkat sabanjuré Catlan Dog. Saiki sampeyan kudu nulis ulang cara kasebut iretateAnimals()supaya bisa digunakake ing kabeh jinis kewan kajaba asu . Collection<Animal>Yaiku, kudu nampa , Collection<Pet>utawa minangka input Collection<Cat>, nanging ora bisa digunakake Collection<Dog>. Kepiye carane bisa nggayuh iki? Katon yen prospek nulis cara sing kapisah kanggo saben jinis bakal ana maneh: / Kepiye carane bisa nerangake logika kita menyang kompiler? Lan iki bisa ditindakake kanthi gampang! Ing kene, wildcard bakal nulungi maneh. Nanging wektu iki kita bakal nggunakake jinis sing beda - " super " (jeneng liya Lower Bounded Wildcards ).
public static void iterateAnimals(Collection<? super Cat> animals) {

   for(int i = 0; i < animals.size(); i++) {

       System.out.println("Еще один шаг в цикле пройден!");
   }
}
Prinsip ing kene padha. Konstruksi kasebut <? super Cat>ngandhani kompiler yen metode kasebut iterateAnimals()bisa digunakake minangka input koleksi obyek saka kelas Catutawa kelas leluhur liyane Cat. CatIng kasus kita, kelas kasebut dhewe , leluhure - Pets, lan leluhure leluhur - cocog karo katrangan iki Animal. Kelas kasebut Dogora cocog karo watesan iki, mula nyoba nggunakake metode kanthi dhaptar List<Dog>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);

   //ошибка компиляции!
   iterateAnimals(dogs);
}
Masalah kita wis ditanggulangi, lan maneh wildcards dadi banget migunani :) Iki rampung kuliah. Saiki sampeyan ndeleng carane penting topik generik nalika sinau basa Jawa - kita nglampahi 4 ceramah ing! Nanging saiki sampeyan wis ngerti topik kasebut lan bakal bisa mbuktekake dhewe ing wawancara :) Lan saiki wektune kanggo bali menyang tugas! Good luck ing pasinaon! :)
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION