JavaRush /Java Blog /Random-TK /Oýlanma API. Oýlanma. Java-nyň garaňky tarapy
Oleksandr Klymenko
Dereje
Харків

Oýlanma API. Oýlanma. Java-nyň garaňky tarapy

Toparda çap edildi
Salam, ýaş Padawan. Bu makalada java programmistleriniň güýji diňe umytsyz ýaly görünýän güýçde ulanýan Güýç hakda aýdaryn. Şeýlelikde, Java-yň garaňky tarapy -Reflection API
Oýlanma API.  Oýlanma.  Java-yň garaňky tarapy - 1
Java-da şöhlelenme Java Reflection API ulanyp amala aşyrylýar. Bu şöhlelenme näme? Gysga we takyk kesgitleme bar, ol internetde hem meşhur. Oýlanma (Latyn latyn refleksiýasyndan - yza gaýdyp barmak) bir programma ýerine ýetirilende maglumatlary öwrenmek üçin mehanizmdir. Oýlanma, meýdanlar, usullar we synp gurluşykçylary baradaky maglumatlary gözden geçirmäge mümkinçilik berýär. Oýlanmak mehanizminiň özi düzmek wagtynda ýok, ýöne programma ýerine ýetirilende ýüze çykan görnüşleri gaýtadan işlemäge mümkinçilik berýär. Eralňyşlyklary habar bermek üçin oýlanmak we logiki taýdan sazlaşykly modeliň bolmagy dogry dinamiki kod döretmäge mümkinçilik berýär. Başgaça aýdylanda, java-da şöhlelenmäniň nähili işleýändigine düşünmek size birnäçe ajaýyp mümkinçilikleri açýar. Göçme manyda Sapaklary we olaryň böleklerini birleşdirip bilersiňiz.
Oýlanma API.  Oýlanma.  Java-yň garaňky tarapy - 2
Ine, şöhlelenmäniň nämäniň rugsat berýändiginiň esasy sanawy:
  • Obýektiň synpyny tapmak / kesgitlemek;
  • Synp üýtgedijileri, meýdanlary, usullary, yzygiderliligi, konstruktorlary we superklasslary barada maglumat alyň;
  • Geçirilen interfeýslere / interfeýslere haýsy usullara degişlidigini anyklaň;
  • Synpyň mysalyny dörediň we programma ýerine ýetirilýänçä synpyň ady belli däl;
  • Obýekt meýdanynyň bahasyny alyň we belläň;
  • Obýektiň usulyna at bilen jaň ediň.
Oýlanma häzirki zaman Java tehnologiýalarynyň hemmesinde diýen ýaly ulanylýar. Java-yň platforma hökmünde şöhlelenmezden şeýle ullakan ogullyga ýetip biljekdigini göz öňüne getirmek kyn. Edip bilmedim. Oýlanmagyň umumy teoretiki pikiri bilen tanyş bolduňyz, indi onuň amaly ulanylyşyna geçeliň! Reflection API-iň ähli usullaryny öwrenmeris, diňe iş ýüzünde duş gelýän zatlar. Oýlanmak mehanizmi synplar bilen işlemegi öz içine alýandygy sebäpli, bizde ýönekeý synp bolar - MyClass:
public class MyClass {
   private int number;
   private String name = "default";
//    public MyClass(int number, String name) {
//        this.number = number;
//        this.name = name;
//    }
   public int getNumber() {
       return number;
   }
   public void setNumber(int number) {
       this.number = number;
   }
   public void setName(String name) {
       this.name = name;
   }
   private void printData(){
       System.out.println(number + name);
   }
}
Görşümiz ýaly, bu iň köp ýaýran synp. Parametrleri bolan konstruktor bir sebäbe görä düşündirilýär, bu meselä soňrak dolanarys. Synpyň mazmunyna ýakyndan göz aýlasaň, belki, gettera üçin a ýoklugyny görersiň name. Meýdanyň özi namegiriş üýtgediji bilen bellendi private, biz synpyň daşynda girip bilmeris, =>bahasyny alyp bilmeris. "Onda näme problema bar? - sen diýýäñ. " getterGiriş modifikatoryny goşuň ýa-da üýtgediň." Dogry aýdarsyňyz, ýöne MyClassdüzülen aar kitaphanasynda ýa-da girişi redaktirlemän başga bir ýapyk modulda bolsa we iş ýüzünde bu ýygy-ýygydan bolýar. Käbir ünssiz programmist ýazmagy ýatdan çykardy getter. Oýlanmak hakda ýatlamagyň wagty geldi! Synp privatemeýdanyna çykmaga synanyşalyň : nameMyClass
public static void main(String[] args) {
   MyClass myClass = new MyClass();
   int number = myClass.getNumber();
   String name = null; //no getter =(
   System.out.println(number + name);//output 0null
   try {
       Field field = myClass.getClass().getDeclaredField("name");
       field.setAccessible(true);
       name = (String) field.get(myClass);
   } catch (NoSuchFieldException | IllegalAccessException e) {
       e.printStackTrace();
   }
   System.out.println(number + name);//output 0default
}
Geliň indi bu ýerde näme bolandygyny anyklalyň. Java-da ajaýyp synp bar Class. Executerine ýetirilýän Java programmasynda synplary we interfeýsleri görkezýär. ClassArasyndaky baglanyşyga degip bilmeris ClassLoader. bu makalanyň mowzugy däl. Ondan soň, bu synpyň meýdanlaryny almak üçin usula jaň etmeli getFields(), bu usul synpyň bar bolan meýdanlaryna bize gaýdyp geler. Bu, biziň üçin amatly däl, sebäbi meýdançamyz private, şonuň üçin usuly ulanýarys getDeclaredFields(). Bu usul bir topar synp meýdanlaryny hem gaýtaryp berýär, ýöne indi ikisi privatehem protected. Biziň ýagdaýymyzda, bizi gyzyklandyrýan meýdanyň adyny bilýäris we islenýän meýdanyň ady getDeclaredField(String)nirede bolsa usuly ulanyp bileris.StringBellik: getFields()getDeclaredFields()ene-atalar synpynyň meýdanlaryny yzyna gaýtarmaň ! Field Ajaýyp, özümize baglanyşyk bolan bir obýekt aldyk name. Sebäbi meýdan публичным(köpçülik) däldi, onuň bilen işlemek üçin ygtyýar berilmeli. Usul setAccessible(true)bize işlemegi dowam etdirmäge mümkinçilik berýär. Indi meýdan namedoly gözegçilikde! Biziň synpymyzyň mysaly bolan obýekte get(Object)jaň edip, onuň bahasyny alyp bilersiňiz . Ony zyňýarys we üýtgeýjimize belläris . Birden 'a' ýok bolsa , at meýdany üçin täze baha bellemek üçin usuly ulanyp bileris : FieldObjectMyClassStringnamesetterset
field.set(myClass, (String) "new value");
Gutlaýarys! Justaňy şöhlelenmegiň esasy mehanizmini özleşdirdiňiz we meýdana girip bildiňiz private! Bloklara try/catchwe ulanylýan kadadan çykma görnüşlerine üns beriň. IDE-iň özi hökmany barlygyny görkezer, ýöne olaryň adynyň bu ýere gelmeginiň sebäbini görkezýär. Dowam et! Üns beren bolsaňyz, MyClasssynp maglumatlarymyz barada maglumatlary görkezmek üçin eýýäm bir usulymyz bar:
private void printData(){
       System.out.println(number + name);
   }
Emma bu programmist bu ýerde-de miras galdyrdy. Usul giriş üýtgeýjisiniň aşagyndady privatewe her gezek çykyş koduny özümiz ýazmaly bolduk. Bu tertipli däl, pikirimiz nirede? ... Geliň, aşakdaky funksiýany ýazalyň:
public static void printData(Object myClass){
   try {
       Method method = myClass.getClass().getDeclaredMethod("printData");
       method.setAccessible(true);
       method.invoke(myClass);
   } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
       e.printStackTrace();
   }
}
Bu ýerde prosedura takmynan bir meýdan almak bilen deňdir - islenýän usuly at bilen alýarys we oňa girýäris. MethodUlanylýan obýektimize jaň etmek üçin invoke(Оbject, Args), Оbjectsynpyň mysaly hem bar MyClass. Args- usul argumentleri - biziňkiler ýok. Indi maglumatlary görkezmek üçin funksiýany ulanýarys printData:
public static void main(String[] args) {
   MyClass myClass = new MyClass();
   int number = myClass.getNumber();
   String name = null; //?
   printData(myClass); // outout 0default
   try {
       Field field = myClass.getClass().getDeclaredField("name");
       field.setAccessible(true);
       field.set(myClass, (String) "new value");
       name = (String) field.get(myClass);
   } catch (NoSuchFieldException | IllegalAccessException e) {
       e.printStackTrace();
   }
   printData(myClass);// output 0new value
}
Hurray, indi synpyň hususy usulyna girip bileris. Methodöne bu usulda henizem argumentler bar bolsa we näme üçin teswirli konstruktor bar? Her zadyň wagty bar. Ilkibaşdaky kesgitlemeden, şöhlelenmäniň size re modeimde runtime(programma işleýän wagtynda) synp mysallaryny döretmäge mümkinçilik berýändigi düşnüklidir! Şol synpyň doly hünärli ady bilen synpyň obýektini döredip bileris. Doly hünärli synpyň ady, oňa barýan ýoly göz öňünde tutup, synpyň adydyr package.
Oýlanma API.  Oýlanma.  Java-yň garaňky tarapy - 3
Ierarhiýamda packagedoly ady MyClass“” bolar reflection.MyClass. Şeýle hem synpyň adyny ýönekeý usulda tapyp bilersiňiz (synpyň adyny setir hökmünde yzyna getirer):
MyClass.class.getName()
Oýlanmak arkaly synpyň mysalyny döredeliň:
public static void main(String[] args) {
   MyClass myClass = null;
   try {
       Class clazz = Class.forName(MyClass.class.getName());
       myClass = (MyClass) clazz.newInstance();
   } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
       e.printStackTrace();
   }
   System.out.println(myClass);//output created object reflection.MyClass@60e53b93
}
Java programmasy başlan wagty hemme synplar JVM-e ýüklenenok. Koduňyz klasa degişli däl bolsa MyClass, sapaklary JVM-e ýüklemek üçin jogapkär adam, ýagny ClassLoaderhiç haçan ol ýere ýüklemez. ClassLoaderŞol sebäpden, üýtgeýän görnüş görnüşinde synpymyzyň beýanyny ýüklemäge we almaga mejbur etmeli Class. Bu ýumuş üçin, düşündiriş talap edýän synpyň ady nirede, forName(String)bir usul bar . StringAlnansoň , şol bir düşündirişe görä dörediljek Сlassusul jaňy newInstance()gaýdyp geler . ObjectBu obýekti synpymyza getirmek galýar MyClass. Salkyn! Kyn boldy, ýöne düşnükli diýip umyt edýärin. Indi sözüň doly manysynda bir setirden mysal döredip bileris! Gynansagam, beýan edilen usul diňe deslapky konstruktor bilen işleýär (parametrlersiz). Argumentler we parametrler bilen konstruktorlar bilen usullary nädip çagyrmaly? Gurluşykçymyzy aýyrmagyň wagty geldi. Garaşylyşy ýaly, newInstance()deslapky konstruktory tapmaýar we indi işlemeýär. Synp mysalynyň döredilmegini täzeden ýazalyň:
public static void main(String[] args) {
   MyClass myClass = null;
   try {
       Class clazz = Class.forName(MyClass.class.getName());
       Class[] params = {int.class, String.class};
       myClass = (MyClass) clazz.getConstructor(params).newInstance(1, "default2");
   } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
       e.printStackTrace();
   }
   System.out.println(myClass);//output created object reflection.MyClass@60e53b93
}
Synp konstruktorlaryny almak üçin usuly synp synpyndan çagyryň getConstructors()we konstruktoryň parametrlerini almak üçin jaň ediň getParameterTypes():
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
   Class[] paramTypes = constructor.getParameterTypes();
   for (Class paramType : paramTypes) {
       System.out.print(paramType.getName() + " ");
   }
   System.out.println();
}
Şeýlelik bilen, ähli konstruktorlary we ähli parametrleri olara alýarys. Mysal üçin, belli, eýýäm belli parametrleri bolan belli bir konstruktora jaň bar. newInstanceBu konstruktory çagyrmak üçin bu parametrleriň bahalaryny kesgitleýän usuly ulanýarys . invokeÇagyryş usullary üçin hem şeýle bolar . Sorag ýüze çykýar: gurluşykçylaryň şöhlelendiriji çagyryşy nirede peýdaly bolup biler? Başda aýdylyşy ýaly häzirki zaman java tehnologiýalary, Reflection API bolmasa edip bilmez. Mysal üçin, DI (Dependency Injection), bu ýerde düşündirişler usullaryň we konstruktorlaryň şöhlelenmesi bilen utgaşyp, Android ösüşinde meşhur bolan Dagger kitaphanasyny emele getirýär. Bu makalany okanyňyzdan soň, “Reflection API” mehanizmlerinde özüňizi ýagtylandyryp bilersiňiz. Munuň üçin “java” -yň garaňky tarapy diýilýär. OOP paradigmasyny düýbünden bozýar. Java-da, encapsulation käbir programma bölekleriniň beýlekilerine elýeterliligini gizlemek we çäklendirmek üçin hyzmat edýär. Hususy üýtgedijini ulanmak bilen, bu meýdana girmek diňe bu meýdanyň bar bolan synpynda boljakdygyny aňladýarys, şonuň esasynda programmanyň mundan beýläkki arhitekturasyny gurýarys. Bu makalada, islendik ýere barmak üçin şöhlelenmäni nädip ulanyp boljakdygyny gördük. Binagärlik çözgüdi görnüşinde oňat mysal döredijilik dizaýn nagşydyr - Singleton. Esasy pikiri, programmanyň tutuş işinde bu şablony amala aşyrýan synpyň diňe bir nusgasy bolmaly. Bu, deslapky giriş üýtgedijisini konstruktor üçin şahsylaşdyrmak arkaly amala aşyrylýar. Käbir programmist öz pikiri bilen şeýle sapaklary döretse gaty erbet bolar. Theeri gelende aýtsak, ýaňy-ýakynda işgärimden eşiden gaty gyzykly bir sorag bar: şablony amala aşyrýan synpyň Singletonmirasdüşerleri bolup bilermi? Bu ýagdaýda hatda pikirlenmegiň hem güýji ýokmy? Makala baradaky pikiriňizi we jogabyňyzy teswirlerde ýazyň we soraglaryňyzy beriň! “Reflection API” -niň hakyky güýji “Runtime Annotations” bilen utgaşýar, bu hakda geljekde Java-yň garaňky tarapy hakda gürleşeris. Üns bereniňiz üçin sag boluň!
Teswirler
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION