JavaRush /Java Blog /Random-TK /Öçürmek görnüşleri

Öçürmek görnüşleri

Toparda çap edildi
Salam! Generika boýunça leksiýalarymyzy dowam etdirýäris. Ozal munuň nämedigini we näme üçin zerurdygyny umumy manyda kesgitledik. Bu gün umumy önümleriň käbir aýratynlyklary barada gürleşeris we olar bilen işleşenimizde käbir kemçiliklere serederis. Git! Geçen leksiýadaGörnüşleri pozuň - 1 umumy görnüşler bilen çig görnüşleriň arasyndaky tapawut barada gürleşdik . Forgetatdan çykaran bolsaňyz, çig görnüş görnüşi aýrylan umumy synpdyr.
List list = new ArrayList();
Ine bir mysal. Bu ýerde haýsy obýektleriň haýsy görnüşde ýerleşdiriljekdigini kesgitlemeýäris List. Birini döredip List, oňa käbir zatlary goşjak bolsak, IDEa-da duýduryş göreris:

“Unchecked call to add(E) as a member of raw type of java.util.List”.
Şeýle hem, generikleriň diňe Java 5 wersiýasynda peýda bolandygy barada gürleşdik. Çykan wagty programmistler Çig görnüşleri ulanyp köp işleýärdi we işlemezligi, başarnygy Java-da çig görnüşleri döretmek we işlemek saklandy. Şeýle-de bolsa, bu mesele has giňeldi. Java kody, bilşiňiz ýaly, ýörite wirtual koda öwrülýär, soňra Java wirtual maşyn tarapyndan ýerine ýetirilýär. Terjimäniň dowamynda parametrleriň görnüşleri barada maglumatlary kod koduna ýerleşdiren bolsak, öň ýazylan kodlaryň hemmesini bozardy, sebäbi Java 5-den ozal hiç hili parametr görnüşi ýokdy! “Generics” bilen işleýän wagtyňyz, ýadyňyzda saklamaly bir möhüm aýratynlyk bar. Görnüşi pozmak diýilýär. Onuň düýp manysy, parametr görnüşi barada hiç hili maglumatyň synpyň içinde saklanmazlygyndadyr. Bu maglumatlar diňe düzmek tapgyrynda elýeterlidir we iş wagtynda pozulýar (elýeterli däl). Nädogry görnüşdäki bir obýekti özüňize saljak bolsaňyz List<String>, düzüji ýalňyşlyk goýberer. Diliň döredijileriniň umumylyklary döretmek arkaly gazananlary - jemleýiş tapgyrynda barlaglar. Youöne ýazýan ähli Java koduňyz kod koduna öwrülende, parametr görnüşleri barada maglumat bolmaz. Kod kodunyň içinde pişikleriň sanawy setirlerden List<Cat>tapawutlanmaz List<String>. catsKod kodundaky hiç zat munuň obýektleriň sanawydygyny aýtmaz Cat. Compygyndy wagtynda bu baradaky maglumatlar öçüriler we diňe programmaňyzda belli bir sanawyňyz bar bolan maglumatlar baýt koduna girer List<Object> cats. Onuň nähili işleýändigini göreliň:
public class TestClass<T> {

   private T value1;
   private T value2;

   public void printValues() {
       System.out.println(value1);
       System.out.println(value2);
   }

   public static <T> TestClass<T> createAndAdd2Values(Object o1, Object o2) {
       TestClass<T> result = new TestClass<>();
       result.value1 = (T) o1;
       result.value2 = (T) o2;
       return result;
   }

   public static void main(String[] args) {
       Double d = 22.111;
       String s = "Test String";
       TestClass<Integer> test = createAndAdd2Values(d, s);
       test.printValues();
   }
}
Öz umumy synpymyzy döretdik TestClass. Bu gaty ýönekeý: aslynda 2 obýektden ybarat kiçijik “ýygyndy” bolup, obýekt döredilende derrew ýerleşdirilýär. Meýdan hökmünde 2 obýekt bar T. Usul ýerine ýetirilende, geçen iki obýekt biziň görnüşimize atylmalydyr createAndAdd2Values(), şondan soň obýekte goşular . Döredýän usulymyzda , ýagny hil taýdan bolar . Theöne şol bir wagtyň özünde, san we bir obýekt usulyna geçirýäris . Maksatnamamyz işlär öýdýärsiňizmi? Galyberse-de, parametr görnüşi hökmünde kesgitledik , ýöne elbetde zyňyp bolmaz ! Usuly işledeliň we barlalyň. Konsol çykyşy: 22.111 Synag setiri Garaşylmadyk netije! Näme üçin beýle boldy? Takyk görnüşi pozulmagy sebäpli. Kod düzülende obýektimiziň parametr görnüşi baradaky maglumatlar öçürildi. Ol öwrüldi . Parametrlerimiz hiç hili kynçylyksyz üýtgedildi ( we garaşyşymyz ýaly däl!) We ýuwaşlyk bilen goşuldy . Ine, görnüşi pozmagyň başga bir ýönekeý, ýöne gaty aýdyň mysaly: Object aObject bTTestClassmain()TestClass<Integer>TIntegercreateAndAdd2Values()DoubleStringIntegerStringIntegermain()IntegerTestClass<Integer> testTestClass<Object> testDoubleStringObjectIntegerTestClass
import java.util.ArrayList;
import java.util.List;

public class Main {

   private class Cat {

   }

   public static void main(String[] args) {

       List<String> strings = new ArrayList<>();
       List<Integer> numbers = new ArrayList<>();
       List<Cat> cats = new ArrayList<>();

       System.out.println(strings.getClass() == numbers.getClass());
       System.out.println(numbers.getClass() == cats.getClass());

   }
}
Konsol çykyşy: hakyky hakykat Üç dürli parametr görnüşi bolan kolleksiýalary döreden ýaly - Stringwe Integerdöreden synpymyz Cat. Byöne bytekoda öwrülende üç sanawyň hemmesi öwrüldi List<Object>, şonuň üçin ýerine ýetirilende programma üç ýagdaýda-da bir synpy ulanýandygymyzy aýdýar.

Toplumlar we generikler bilen işleýän wagtyňyz pozmagy ýazyň

Toplumlar we generikler bilen işlän wagtyňyz anyk düşünmeli bir möhüm nokat bar (mysal üçin List). Programmaňyz üçin maglumat gurluşyny saýlanyňyzda hem göz öňünde tutmalydyrys. Generikler görnüşi pozulmalydyr. Programmanyň ýerine ýetirilişinde parametr görnüşi barada maglumat elýeterli däl. Munuň tersine, massiwler programma ýerine ýetirilende maglumatlaryň görnüşi baradaky maglumatlary bilýär we ulanyp biler. Nädogry görnüşiň bahasyny massiwde goýmaga synanyşmak kadadan çykma döreder:
public class Main2 {

   public static void main(String[] args) {

       Object x[] = new String[3];
       x[0] = new Integer(222);
   }
}
Konsol çykyşy:

Exception in thread "main" java.lang.ArrayStoreException: java.lang.Integer
Toplumlar bilen generikleriň arasynda şeýle uly tapawut barlygy sebäpli, utgaşyklyk meselesi bolup biler. Ilki bilen, umumy obýektleriň toplumyny ýa-da diňe ýazylan massiw döredip bilmersiňiz. Biraz bulaşyk sesler? Geliň, has içgin seredeliň. Mysal üçin, Java-da bularyň hiç birini edip bilmersiňiz:
new List<T>[]
new List<String>[]
new T[]
Sanawlaryň bir toparyny döretmäge synanyşsak List<String>, umumy massiw döretmek düzüliş ýalňyşlygy alarys:
import java.util.List;

public class Main2 {

   public static void main(String[] args) {

       //ошибка компиляции! Generic array creation
       List<String>[] stringLists = new List<String>[1];
   }
}
Emma näme üçin beýle edildi? Näme üçin beýle massiwleri döretmek gadagan? Bularyň hemmesi görnüşiň howpsuzlygyny üpjün etmek üçin. Eger düzüji umumy obýektlerden şeýle massiwleri döretmäge rugsat beren bolsa, köp kynçylyklara sezewar bolup bileris. Ine, Joşua Bloçyň “Netijeli Java” atly kitabyndan ýönekeý bir mysal:
public static void main(String[] args) {

   List<String>[] stringLists = new List<String>[1];  //  (1)
   List<Integer> intList = Arrays.asList(42, 65, 44);  //  (2)
   Object[] objects = stringLists;  //  (3)
   objects[0] = intList;  //  (4)
   String s = stringLists[0].get(0);  //  (5)
}
Geliň, massiw döretmäge List<String>[] stringListsrugsat berler we düzüji arz etmez. Ine, bu ýagdaýda näme edip bileris: 1-nji setirde bir topar sahypany döredýäris List<String>[] stringLists. Biziň massiwimizde biri bar List<String>. 2-nji setirde sanlaryň sanawyny döredýäris List<Integer>. 3-nji setirde massiwimizi List<String>[]üýtgeýjä belläris Object[] objects. Java dili muny etmäge mümkinçilik berýär: ähli çaga synplarynyň Xobýektlerini we obýektlerini obýektleriň hataryna goýup bilersiňiz . Şoňa görä-de, islendik zady massiwde goýup bilersiňiz. 4-nji setirde massiwiň ýekeje elementini sanaw bilen çalyşýarys . Netijede, diňe saklamak üçin niýetlenen massiwimize ýerleşdirdik ! Diňe kod 5-nji setire ýeteninde ýalňyşlyk bilen ýüzbe-ýüz bolarys. Programma ýerine ýetirilende kadadan çykma bolar . Şonuň üçin şeýle massiwleri döretmegiň gadaganlygy Java diline girizildi - bu bize şeýle ýagdaýlardan gaça durmaga mümkinçilik berýär. XХObjectsobjects (List<String>)List<Integer>List<Integer>List<String>ClassCastException

Görnüşi pozmagy nädip aýlap bilerin?

Dogrusy, görnüşi pozmagy öwrendik. Ulgamy aldatmaga synanyşalyň! :) Wezipe: Bizde umumy synp bar TestClass<T>. createNewT()Onda täze görnüşli obýekt döredýän we yzyna gaýtarjak usul döretmeli Т. Emma muny etmek mümkin däl, şeýlemi? Görnüşi baradaky ähli maglumatlar Тdüzülende ýok ediler we programma işleýän wagtynda haýsy obýekti döretmelidigimizi bilip bilmeris. Aslynda, bir kyn ýol bar. Java-da bir synpyň bardygyny ýadyňyzda bolsa gerek Class. Ony ulanyp, islendik obýektimiziň synpyny alyp bileris:
public class Main2 {

   public static void main(String[] args) {

       Class classInt = Integer.class;
       Class classString = String.class;

       System.out.println(classInt);
       System.out.println(classString);
   }
}
Konsol çykyşy:

class java.lang.Integer
class java.lang.String
Hereöne bu ýerde gürleşmedik bir aýratynlygymyz bar. Oracle resminamalarynda synpyň umumy synpdygyny görersiňiz! Görnüşleri pozuň - 3Resminamalarda: "T - bu synp obýekti tarapyndan modellenen synpyň görnüşi." Muny resminama dilinden adam diline terjime etsek, bu bir obýekt üçin synpyň Integer.classdiňe bir däl Class, eýsem Class<Integer>. Obýektiň görnüşi string.classdiňe bir Classwe Class<String>ş.m. Entek düşnüksiz bolsa, öňki mysala görnüş parametrini goşup görüň:
public class Main2 {

   public static void main(String[] args) {

       Class<Integer> classInt = Integer.class;
       //ошибка компиляции!
       Class<String> classInt2 = Integer.class;


       Class<String> classString = String.class;
       //ошибка компиляции!
       Class<Double> classString2 = String.class;
   }
}
Indi bolsa, bu bilimlerden peýdalanyp, görnüşi pozmakdan aýlanyp, meselämizi çözüp bileris! Parametriň görnüşi barada maglumat almaga synanyşalyň. Onuň roly synp tarapyndan ýerine ýetiriler MySecretClass:
public class MySecretClass {

   public MySecretClass() {

       System.out.println("Объект секретного класса успешно создан!");
   }
}
Ine, çözgüdimizi iş ýüzünde nähili ulanýarys:
public class TestClass<T> {

   Class<T> typeParameterClass;

   public TestClass(Class<T> typeParameterClass) {
       this.typeParameterClass = typeParameterClass;
   }

   public T createNewT() throws IllegalAccessException, InstantiationException {
       T t = typeParameterClass.newInstance();
       return t;
   }

   public static void main(String[] args) throws InstantiationException, IllegalAccessException {

       TestClass<MySecretClass> testString = new TestClass<>(MySecretClass.class);
       MySecretClass secret = testString.createNewT();

   }
}
Konsol çykyşy:

Объект секретного класса успешно создан!
Diňe zerur synp parametrini umumy synpymyzyň konstruktoryna geçirdik:
TestClass<MySecretClass> testString = new TestClass<>(MySecretClass.class);
Munuň netijesinde parametrleriň görnüşi baradaky maglumatlary ýatda sakladyk we pozulmagyndan goradyk. Netijede, bir obýekt döredip bildik T! :) Bu, şu günki leksiýamyzy tamamlaýar. Generika bilen işleýän wagtyňyz görnüşi pozmak elmydama ýatda saklamaly zat. Bu gaty amatly görünmeýär, ýöne generikleriň döredilende Java diliniň bir bölegi däldigine düşünmeli. Bu, ýazylan kolleksiýalary döretmäge we düzmek tapgyrynda ýalňyşlyklary tutmaga kömek edýän soňraky goşulan aýratynlyk. Generikleriň 1-nji wersiýasyndan bäri bar bolan käbir beýleki dillerde görnüşi pozulmaýar (mysal üçin, C #). Şeýle-de bolsa, biz generikany öwrenenok! Indiki leksiýada olar bilen işlemegiň ýene birnäçe aýratynlyklary bilen tanyşarsyňyz. Şol aralykda, iki meseläni çözmek gowy bolardy! :)
Teswirler
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION