JavaRush /Blog Jawa /Random-JV /Refleksi API. Refleksi. Sisih Peteng Jawa
Oleksandr Klymenko
tingkat
Харків

Refleksi API. Refleksi. Sisih Peteng Jawa

Diterbitake ing grup
Salam, muda Padawan. Ing artikel iki aku bakal pitutur marang kowe bab Force, daya kang programer java nggunakake mung ing kahanan ketoke ngarep-arep. Dadi, sisih peteng Jawa yaiku -Reflection API
Refleksi API.  Refleksi.  Sisih Peteng Jawa - 1
Refleksi ing Jawa ditindakake nggunakake Java Reflection API. Apa refleksi iki? Ana definisi cendhak lan tepat sing uga populer ing Internet. Refleksi (saka Late Latin reflexio - going back) minangka mekanisme kanggo nyinaoni data babagan program sajrone eksekusi. Refleksi ngidini sampeyan nliti informasi babagan kolom, metode, lan konstruktor kelas. Mekanisme refleksi dhewe ngidini sampeyan ngolah jinis sing ilang sajrone kompilasi, nanging katon sajrone eksekusi program. Refleksi lan anané model logis sing koheren kanggo nglaporake kesalahan ndadekake bisa nggawe kode dinamis sing bener. Ing tembung liyane, ngerti carane refleksi ing Jawa mbukak sawetara kesempatan apik tenan kanggo sampeyan. Sampeyan bisa kanthi harfiah juggle kelas lan komponen.
Refleksi API.  Refleksi.  Sisih Peteng Jawa - 2
Iki minangka dhaptar dhasar babagan apa sing diidini refleksi:
  • Temokake / nemtokake kelas obyek;
  • Entuk informasi babagan modifiers kelas, kolom, metode, konstanta, konstruktor lan superclass;
  • Temokake cara sing kalebu antarmuka / antarmuka sing diimplementasikake;
  • Nggawe conto kelas, lan jeneng kelas ora dingerteni nganti program dieksekusi;
  • Entuk lan atur nilai lapangan obyek kanthi jeneng;
  • Nelpon metode obyek kanthi jeneng.
Refleksi digunakake ing meh kabeh teknologi Jawa modern. Iku angel mbayangno apa Java minangka platform bisa entuk adopsi gedhe banget tanpa refleksi. Paling kamungkinan aku ora bisa. Sampeyan wis kenal karo ide teoretis umum babagan refleksi, saiki ayo goleki aplikasi praktis! Kita ora bakal nyinaoni kabeh metode API Refleksi, mung apa sing ditemoni ing praktik. Wiwit mekanisme refleksi melu nggarap kelas, kita bakal duwe kelas sing prasaja - 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);
   }
}
Minangka kita bisa ndeleng, iki kelas paling umum. Konstruktor karo paramèter wis komentar metu kanggo alesan, kita bakal bali menyang mengko. Yen sampeyan ndeleng kanthi teliti isi kelas, sampeyan bisa uga weruh ora ana getter'a kanggo name. Kolom kasebut dhewe nameditandhani karo modifier akses private; kita ora bakal bisa ngakses ing njaba kelas kasebut; =>kita ora bisa entuk regane. “Lha apa masalahe? - sampeyan ngomong. "Tambah getterutawa ganti modifier akses." Lan sampeyan bakal bener, nanging apa yen MyClassana ing perpustakaan aar nyawiji utawa ing modul ditutup liyane tanpa akses editing, lan ing laku iki kedaden arang banget. Lan sawetara programmer sing ora peduli mung lali nulis getter. Wektu kanggo ngelingi babagan refleksi! Ayo nyoba menyang privatelapangan namekelas MyClass:
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
}
Ayo ngerteni apa sing kedadeyan ing kene saiki. Ana kelas sing apik ing basa Jawa Class. Iki nggambarake kelas lan antarmuka ing aplikasi Java sing bisa dieksekusi. Kita ora bakal tutul ing sambungan antarane Classlan ClassLoader. iki dudu topik artikel. Sabanjure, kanggo entuk lapangan kelas iki, sampeyan kudu nelpon metode getFields(), metode iki bakal bali menyang kabeh lapangan sing kasedhiya ing kelas kasebut. Iki ora cocog kanggo kita, amarga lapangan kita private, mula kita nggunakake metode iki getDeclaredFields(). Cara iki uga ngasilake macem-macem lapangan kelas, nanging saiki loro privatelan protected. Ing kahanan kita, kita ngerti jeneng lapangan sing kapentingan kita, lan kita bisa nggunakake cara getDeclaredField(String), ngendi Stringjeneng lapangan sing dikarepake. Cathetan: getFields()lan getDeclaredFields()aja mbalekake sawahe kelas wong tuwa! Apik banget, kita nampa obyek Field kanthi tautan menyang name. Amarga lapangan iki ora публичным(umum), akses kudu diwenehi kanggo bisa karo. Cara kasebut setAccessible(true)ngidini kita terus kerja. Saiki lapangan namewis rampung ing kontrol kita! Sampeyan bisa entuk regane kanthi nelpon get(Object)obyek kasebut Field, ing ngendi Objectana conto kelas kita MyClass. Kita mbuwang Stringlan nemtokake menyang variabel kita name. Yen dumadakan ora duwe setter'a, kita bisa nggunakake cara kanggo nyetel nilai anyar kanggo kolom jeneng set:
field.set(myClass, (String) "new value");
Sugeng rawuh! Sampeyan wis nguwasani mekanisme dhasar refleksi lan bisa ngakses privatelapangan! Pay manungsa waé menyang pemblokiran try/catchlan jinis pangecualian ditangani. IDE dhewe bakal nuduhake prentah prentah, nanging jenenge nggawe jelas kenapa dheweke ana ing kene. Terusna! Kaya sing sampeyan ngerteni, kita MyClasswis duwe cara kanggo nampilake informasi babagan data kelas:
private void printData(){
       System.out.println(number + name);
   }
Nanging programmer iki uga ninggalake warisan ing kene. Cara kasebut ana ing modifier akses private, lan kita kudu nulis kode output dhewe saben wektu. Ora urut, endi refleksi kita?... Ayo nulis fungsi ing ngisor iki:
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();
   }
}
Ing kene prosedur kasebut kira-kira padha karo njupuk lapangan - kita entuk metode sing dikarepake kanthi jeneng lan menehi akses menyang. Lan kanggo nelpon obyek Methodkita nggunakake invoke(Оbject, Args), ngendi Оbjectuga Kayata saka kelas MyClass. Args- argumen metode - kita ora duwe. Saiki kita nggunakake fungsi kanggo nampilake informasi 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, saiki kita duwe akses menyang metode pribadi kelas. Nanging kepiye yen metode kasebut isih duwe argumen, lan kenapa ana konstruktor sing dikomentari? Kabeh ana wektune. Saka definisi ing wiwitan, jelas yen refleksi ngidini sampeyan nggawe conto kelas ing mode runtime(nalika program mlaku)! Kita bisa nggawe obyek saka kelas kanthi jeneng qualified kelas sing. Jeneng kelas qualified kanthi jeneng kelas, diwenehi path menyang ing package.
Refleksi API.  Refleksi.  Sisih Peteng Jawa - 3
Ing hirarkiku, packagejeneng lengkap MyClassbakal dadi " reflection.MyClass". Sampeyan uga bisa ngerteni jeneng kelas kanthi cara sing gampang (bakal ngasilake jeneng kelas minangka string):
MyClass.class.getName()
Ayo nggawe conto kelas nggunakake refleksi:
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
}
Nalika aplikasi java diwiwiti, ora kabeh kelas dimuat menyang JVM. Yen kode sampeyan ora nuduhake kelas MyClass, wong sing tanggung jawab kanggo mbukak kelas menyang JVM, yaiku ClassLoader, ora bakal mbukak ing kana. Mulane, kita kudu meksa ClassLoaderkanggo mbukak lan nampa gambaran saka kelas kita ing wangun variabel saka jinis Class. Kanggo tugas iki, ana cara forName(String), endi Stringjeneng kelas sing deskripsi sing dibutuhake. Sawise ditampa Сlass, telpon metode newInstance()bakal bali Object, sing bakal digawe miturut katrangan sing padha. Iku tetep kanggo nggawa obyek iki kanggo kelas kita MyClass. Kelangan! Iku angel, nanging muga-muga bisa dingerteni. Saiki kita bisa nggawe conto kelas kanthi harfiah saka siji baris! Sayange, cara sing diterangake mung bakal bisa digunakake karo konstruktor standar (tanpa parameter). Kepiye cara nelpon metode kanthi argumen lan konstruktor kanthi paramèter? Iku wektu kanggo uncomment konstruktor kita. Kaya sing dikarepake, newInstance()ora nemokake konstruktor standar lan ora bisa digunakake maneh. Ayo nulis maneh nggawe conto kelas:
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
}
Kanggo entuk konstruktor kelas, nelpon metode saka deskripsi kelas getConstructors(), lan kanggo entuk paramèter konstruktor, nelpon 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();
}
Kanthi cara iki, kita entuk kabeh konstruktor lan kabeh paramèter kasebut. Ing conto, ana telpon kanggo konstruktor tartamtu karo tartamtu, wis dikenal paramèter. Lan kanggo nelpon konstruktor iki, kita nggunakake cara newInstance, ing ngendi kita nemtokake nilai paramèter kasebut. Sing padha bakal kelakon invokekanggo cara nelpon. Pitakonan muncul: ing ngendi panggilan reflektif konstruktor bisa migunani? Teknologi java modern, kaya sing kasebut ing wiwitan, ora bisa ditindakake tanpa API Refleksi. Contone, DI (Dependency Injection), ngendi anotasi digabungake karo bayangan saka cara lan konstruktor mbentuk perpustakaan Dagger, populer ing pembangunan Android. Sawise maca artikel iki, sampeyan bisa kanthi yakin nganggep awake dhewe wis enlightened ing mekanisme API Refleksi. Ora kanggo apa-apa yen bayangan diarani sisih peteng ing Jawa. Iku rampung ngilangi paradigma OOP. Ing java, enkapsulasi serves kanggo ndhelikake lan matesi akses saka sawetara komponen program kanggo liyane. Kanthi nggunakake modifier pribadi, tegese akses menyang lapangan iki mung ana ing kelas sing ana lapangan iki, adhedhasar iki, kita mbangun arsitektur program kasebut. Ing artikel iki, kita weruh carane sampeyan bisa nggunakake refleksi kanggo tekan ngendi wae. Conto apik ing wangun solusi arsitektur yaiku pola desain generatif - Singleton. Ide utama yaiku sajrone kabeh operasi program, kelas sing ngetrapake cithakan iki kudu mung siji salinan. Iki rampung kanthi nyetel modifikasi akses standar menyang pribadi kanggo konstruktor. Lan bakal ala banget yen sawetara programmer karo bayangan dhewe nggawe kelas kuwi. Ngomong-ngomong, ana pitakonan sing menarik banget sing aku krungu saka karyawanku: apa kelas sing ngetrapake cithakan bisa duwe Singletonahli waris? Apa bisa malah bayangan ora duwe daya ing kasus iki? Tulis tanggapan sampeyan babagan artikel lan wangsulan ing komentar, lan uga takon pitakonan sampeyan! Daya sejati API Refleksi teka ing kombinasi karo Runtime Anotasi, sing bisa uga bakal dibahas ing artikel sabanjure babagan sisih peteng ing Jawa. Matur nuwun kanggo perhatian sampeyan!
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION