CodeGym /Blog Jawa /Acak /Refleksi API: Refleksi. Sisih peteng ing Jawa
John Squirrels
tingkat
San Francisco

Refleksi API: Refleksi. Sisih peteng ing Jawa

Diterbitake ing grup
Salam, muda Padawan. Ing artikel iki, aku bakal nyritakake babagan Force, kekuwatan sing mung digunakake dening programer Java ing kahanan sing ora mungkin. Sisih peteng ing Jawa yaiku API Refleksi. Ing Jawa, refleksi diimplementasikake nggunakake Java Reflection API.

Apa sing diarani refleksi Jawa?

Ana definisi cendhak, akurat, lan populer ing Internet. Refleksi ( saka reflexio Latin pungkasan - kanggo nguripake maneh ) minangka mekanisme kanggo njelajah data babagan program nalika lagi mlaku. Refleksi ngidini sampeyan njelajah informasi babagan lapangan, metode, lan konstruktor kelas. Refleksi ngidini sampeyan nggarap jinis sing ora ana ing wektu kompilasi, nanging kasedhiya sajrone wektu mbukak. Refleksi lan model logis sing konsisten kanggo nerbitake informasi kesalahan ndadekake bisa nggawe kode dinamis sing bener. Ing tembung liyane, pangerten carane refleksi ing Jawa bakal mbukak sawetara kesempatan apik tenan kanggo sampeyan. Sampeyan bisa kanthi harfiah juggle kelas lan komponen. Iki minangka dhaptar dhasar babagan apa sing diidini refleksi:
  • Sinau / nemtokake kelas obyek;
  • Entuk informasi babagan modifier, kolom, metode, konstanta, konstruktor, lan superclass;
  • Temokake metode apa sing kalebu antarmuka sing diimplementasikake;
  • Nggawe conto kelas sing jeneng kelas ora dingerteni nganti wektu mbukak;
  • Entuk lan nyetel nilai kolom obyek kanthi jeneng;
  • Nelpon metode obyek kanthi jeneng.
Refleksi digunakake ing meh kabeh teknologi Jawa modern. Iku angel mbayangno yen Jawa, minangka platform, bisa entuk adopsi sing nyebar tanpa dipikirake. Paling kamungkinan, iku ora bakal duwe. Saiki yen sampeyan wis ngerti babagan refleksi minangka konsep teoretis, ayo nerusake aplikasi praktis! Kita ora bakal sinau kabeh metode Reflection API-mung sing bakal sampeyan temoni ing praktik. Wiwit refleksi kalebu nggarap kelas, kita bakal miwiti karo kelas prasaja sing diarani 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);
   }
}
Nalika sampeyan bisa ndeleng, iki kelas banget dhasar. Konstruktor kanthi paramèter sengaja dikomentari. Kita bakal bali menyang mengko. Yen katon kasebut kanthi teliti, ing isi kelas, sampeyan mbokmenawa ngeweruhi anané getter kanggo lapangan jeneng . Kolom jeneng dhewe ditandhani karo modifier akses pribadi : kita ora bisa ngakses ing njaba kelas dhewe sing tegese kita ora bisa njupuk regane . " Dadi masalahe apa ?" sampeyan ngomong. "Tambah getter utawa ngganti modifier akses". Lan sampeyan bakal bener, kajabaMyClassana ing perpustakaan AAR kompilasi utawa ing modul pribadi liyane tanpa kemampuan kanggo owah-owahan. Ing laku, iki kedadeyan kabeh wektu. Lan sawetara programmer sing ora peduli mung lali nulis getter . Iki wektu banget kanggo ngelingi refleksi! Ayo coba menyang lapangan jeneng pribadi kelas 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 analisa apa sing lagi wae kedadeyan. Ing tlatah Jawa ana kelas kang endah arane Class. Iki nggambarake kelas lan antarmuka ing aplikasi Java sing bisa dieksekusi. Kita ora bakal nutupi hubungan antarane Classlan ClassLoader, amarga iku dudu topik artikel iki. Sabanjure, kanggo njupuk lapangan kelas iki, sampeyan kudu nelpon getFields()cara. Cara iki bakal ngasilake kabeh lapangan sing bisa diakses kelas iki. Iki ora bisa digunakake kanggo kita, amarga lapangan kita pribadi , mula kita nggunakake getDeclaredFields()metode kasebut. Cara iki uga ngasilake macem-macem lapangan kelas, nanging saiki kalebu lapangan pribadi lan dilindhungi . Ing kasus iki, kita ngerti jeneng lapangan kita kasengsem ing, supaya kita bisa nggunakake getDeclaredField(String)cara, ngendiStringiku jeneng kolom sing dikarepake. Cathetan: getFields()lan getDeclaredFields()aja mbalekake sawahe kelas wong tuwa! Agung. Kita entuk Fieldobyek sing nyebutake jeneng kita . Amarga lapangan kasebut ora umum , kita kudu menehi akses kanggo nggarap. Cara kasebut setAccessible(true)ngidini kita nerusake. Saiki lapangan jeneng ing kontrol lengkap kita! Sampeyan bisa njupuk regane kanthi nelpon metode Fieldobyek get(Object), ing ngendi Objectana conto MyClasskelas kita. Kita ngowahi jinis kasebut Stringlan nemtokake nilai kasebut menyang variabel jeneng kita . Yen kita ora bisa nemokake setter kanggo nyetel nilai anyar menyang kolom jeneng, sampeyan bisa nggunakake cara nyetel :

field.set(myClass, (String) "new value");
Sugeng rawuh! Sampeyan wis nguwasani dhasar refleksi lan ngakses lapangan pribadi ! Pay manungsa waé kanggo pemblokiran try/catch, lan jinis pangecualian ditangani. IDE bakal menehi pitutur marang kowe yen ana sing dibutuhake dhewe, nanging sampeyan bisa ngerti kanthi jelas jenenge kenapa dheweke ana ing kene. Ngalih! Kaya sing sampeyan ngerteni, MyClasskelas kita wis duwe metode kanggo nampilake informasi babagan data kelas:

private void printData(){
       System.out.println(number + name);
   }
Nanging programmer iki uga ninggalake bekas driji ing kene. Cara kasebut nduweni modifier akses pribadi , lan kita kudu nulis kode dhewe kanggo nampilake data saben wektu. Kacau tenan. Ngendi bayangan kita? Tulis 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();
   }
}
Prosedur ing kene meh padha karo sing digunakake kanggo njupuk lapangan. Kita ngakses cara sing dikarepake kanthi jeneng lan menehi akses menyang. Lan ing Methodobyek kita nelpon invoke(Object, Args)cara, ngendi Objectuga Kayata saka MyClasskelas. Argsminangka argumen metode, sanajan kita ora duwe. Saiki kita nggunakake printDatafungsi kanggo nampilake informasi:

public static void main(String[] args) {
   MyClass myClass = new MyClass();
   int number = myClass.getNumber();
   String name = null; //?
   printData(myClass); // Output: 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
}
Hore! Saiki kita duwe akses menyang metode pribadi kelas. Nanging kepiye yen metode kasebut duwe argumen, lan kenapa konstruktor menehi komentar? Kabeh ing wektune dhewe. Cetha saka definisi ing wiwitan yen refleksi ngidini sampeyan nggawe conto kelas nalika mbukak (nalika program lagi mlaku)! Kita bisa nggawe obyek nggunakake jeneng lengkap kelas. Jeneng lengkap kelas yaiku jeneng kelas, kalebu path paket kasebut .
Refleksi API: Refleksi.  Sisih peteng ing Jawa - 2
Ing hirarki paketku , jeneng lengkap MyClass bakal dadi "reflection.MyClass". Ana uga cara sing gampang kanggo sinau jeneng kelas (baliake jeneng kelas minangka String):

MyClass.class.getName()
Ayo nggunakake refleksi Jawa kanggo nggawe conto kelas:

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, banjur ClassLoader, sing tanggung jawab kanggo mbukak kelas menyang JVM, ora bakal mbukak kelas kasebut. Tegese sampeyan kudu meksa ClassLoadermbukak lan entuk katrangan kelas kanthi bentuk Classvariabel. Pramila kita duwe forName(String)metode, ing ngendi Stringjeneng kelas sing deskripsine dibutuhake. Sawise entuk Сlassobyek kasebut, nelpon metode kasebut newInstance()bakal ngasilake Objectobyek sing digawe nggunakake deskripsi kasebut. Kabeh sing isih ana yaiku nyedhiyakake obyek iki kanggo kitaMyClasskelas. Kelangan! Sing angel, nanging bisa dingerteni, muga-muga. Saiki kita bisa nggawe conto kelas kanthi harfiah siji baris! Sayange, pendekatan sing diterangake mung bakal bisa digunakake karo konstruktor standar (tanpa paramèter). Kepiye cara nelpon metode lan konstruktor kanthi paramèter? Iku wektu kanggo uncomment konstruktor kita. Kaya sing dikarepake, newInstance()ora bisa nemokake konstruktor standar, lan ora bisa digunakake maneh. Ayo nulis ulang instantiation 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
}
Cara kasebut getConstructors()kudu diarani definisi kelas kanggo entuk konstruktor kelas, banjur getParameterTypes()kudu diarani kanggo entuk paramèter konstruktor:

Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
   Class[] paramTypes = constructor.getParameterTypes();
   for (Class paramType : paramTypes) {
       System.out.print(paramType.getName() + " ");
   }
   System.out.println();
}
Sing entuk kabeh konstruktor lan paramèter. Ing conto, aku deleng konstruktor tartamtu karo tartamtu, paramèter sadurunge dikenal. Lan kanggo nelpon konstruktor iki, kita nggunakake newInstancecara, kang kita pass nilai paramèter iki. Iku bakal padha nalika nggunakake invokekanggo nelpon cara. Iki dadi pitakonan: kapan nelpon konstruktor liwat refleksi bisa migunani? Kaya sing wis kasebut ing wiwitan, teknologi Jawa modern ora bisa ditindakake tanpa Java Reflection API. Contone, Dependency Injection (DI), sing nggabungake anotasi karo refleksi metode lan konstruktor kanggo mbentuk Darer sing populer.perpustakaan kanggo pangembangan Android. Sawise maca artikel iki, sampeyan bisa kanthi yakin nganggep awake dhewe wis sinau babagan cara Java Reflection API. Dheweke ora nyebut refleksi minangka sisih peteng ing Jawa. Iku rampung ngilangi paradigma OOP. Ing Jawa, enkapsulasi ndhelikake lan mbatesi akses wong liya menyang komponen program tartamtu. Nalika kita nggunakake modifier pribadi, kita arep kanggo lapangan sing mung bisa diakses saka ing kelas ngendi iku ana. Lan kita mbangun arsitektur sakteruse program adhedhasar prinsip iki. Ing artikel iki, kita wis weruh carane sampeyan bisa nggunakake refleksi kanggo meksa dalan ing ngendi wae. Pola desain ciptaan Singletonminangka conto sing apik babagan iki minangka solusi arsitektur. Ide dhasar yaiku kelas sing ngetrapake pola iki mung bakal duwe siji conto sajrone eksekusi kabeh program. Iki ditindakake kanthi nambah modifier akses pribadi menyang konstruktor standar. Lan bakal dadi ala banget yen programmer nggunakake refleksi kanggo nggawe luwih akeh kelas kasebut. Ngomong-ngomong, aku bubar krungu kanca kerja takon pitakonan sing menarik banget: apa kelas sing ngetrapake pola Singleton bisa diwarisake? Apa bisa dadi, ing kasus iki, malah bayangan bakal ora daya? Ninggalake tanggapan sampeyan babagan artikel lan jawaban sampeyan ing komentar ing ngisor iki, lan takon dhewe ing kana!

Wacan liyane:

Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION