Selain memberi kami berbagai informasi tentang mendapatkan kelas selama periode kompilasi, Java juga memungkinkan kami untuk mendapatkan berbagai informasi tentang kelas selama periode berjalan melalui refleksi. Ambil informasi kelas melalui refleksi dan setelah mendapatkan informasi kelas, Anda dapat memperoleh konten terkait berikut:
Artikel ini juga akan memperkenalkan refleksi Java dari aspek -aspek di atas. Semua kode yang terlibat dalam artikel ini tercermin
Pertama, kelas Java dirilis sebagai objek penelitian untuk refleksi. Isi kelas adalah sebagai berikut:
kelas abstrak public pastorobject mengimplementasikan runnable {public void dosomething () {System.out.println ("Do Things ..."); }} kelas publik ExampleObject Extends FatherObject {Public int Age = 30; name public string = "ByHieg"; Skor integer pribadi = 60; public void printName () {System.out.println (name); } public int getage () {usia kembali; } public void setage (int usia) {this.age = usia; } public string getName () {return name; } public void setName (name string) {this.name = name; } public integer getScore () {skor return; } public void setScore (skor integer) {this.score = skor; } public exampleObject () {} public exampleObject (string name) {} public exampleObject (int usia, skor integer) {} @Override public void dosomething () {super.dosomething (); } @Override public void run () {System.out.println ("run ..."); }}Objek kelas
Aplikasi kami akan menggunakan titik refleksi pengetahuan. Kita harus ingin mendapatkan informasi kelas saat runtime dan melakukan beberapa operasi spesifik berdasarkan informasi kelas. Kemudian, hal pertama adalah mendapatkan informasi kelas, dan objek kelas disediakan di JDK untuk menyimpan informasi kelas. Oleh karena itu, langkah pertama dalam refleksi adalah untuk mendapatkan objek kelas. Ada dua cara untuk mendapatkan objek kelas di JDK.
Yang pertama adalah bahwa jika Anda tahu nama kelas saat menulis kode, Anda dapat secara langsung mendapatkan objek kelas dengan cara berikut:
Class exampleObjectClass = ExampleObject.class;
Tipe kedua adalah bahwa jika Anda tidak tahu nama kelas saat menulis kode, tetapi saat runtime, Anda bisa mendapatkan string dari nama kelas, dan Anda bisa mendapatkan objek kelas dengan cara berikut:
Class exampleObjectClass = Class.forName("cn.byhieg.reflectiontutorial.ExampleObject");
Perhatikan bahwa metode ini perlu memiliki 2 kondisi. Pertama, string dalam forname harus sepenuhnya memenuhi syarat, dan kedua, kelas kelas harus di bawah jalur classpath, karena metode ini akan melemparkan pengecualian classnotfoundException.
Setelah mendapatkan objek kelas ini, Anda bisa mendapatkan berbagai informasi tentang kelas. Beberapa informasi telah disebutkan di awal. Di bawah ini, mari kita bicara tentang informasi tentang kelas yang belum disebutkan.
Dapatkan nama kelas
Ada dua cara untuk mendapatkan nama kelas, satu adalah getName () dan yang lainnya getsimplename (). Yang pertama mendapat nama yang sepenuhnya memenuhi syarat, dan yang kedua mendapat nama kelas ini tanpa nama paket. Lihatlah contoh berikut: Objek kelas, yang telah diperoleh melalui kode di atas.
String fullClassName = exampleObjectClass.getName (); String SimpleClassName = ExampleObjectClass.GetSImplename (); System.out.println (FullClassName); System.out.println (SimpleClassName); System.out.println (SimpleClassName);
Hasilnya adalah sebagai berikut:
cn.byhieg.reflectiontutorial.exampleObjectExampleObject
Dapatkan nama paket kelas, kelas induk dan antarmuka implementasi
Nama paket dan kelas induk kelas dapat diperoleh melalui kode berikut.
// Dapatkan paket informasi paket apackage = exampleObjectclass.getPackage (); System.out.println (Apackage); // Dapatkan kelas Parent Class Superclass = ExampleObjectClass.GetSuperClass (); System.out.println (superclass.getsimplename ());
Hasilnya adalah sebagai berikut:
Paket cn.byhieg.reflectiontutorialFatherObject
Jelas, mendapatkan nilai pengembalian kelas induk juga merupakan objek kelas. Kemudian Anda dapat menggunakan objek ini untuk mendapatkan beberapa informasi tentang kelas induk, seperti menilai apakah kelas induk adalah kelas abstrak.
System.out.println("父类是不是抽象类" + Modifier.isAbstract(superClass.getModifiers()));
GetModifiers bisa mendapatkan pengubah kelas, sehingga mendapatkan pengubah kelas. Tentu saja, getModifiers ini tidak hanya dapat disebut objek kelas, tetapi objek metode dapat dipanggil.
Anda dapat menggunakan metode ini di kelas java.lang.reflect.modifier untuk memeriksa jenis pengubah:
Modifier.isabstract (pengubah int); Modifier.isfinal (pengubah int); Modifier.isInterface (pengubah int); Modifier.isnative (pengubah int); Modifier.isprivate (pengubah Int); Modifier. pengubah); Modifier.ISTRICT (pengubah int); Modifier.issynchronized (pengubah int); Modifier.istransient (pengubah int); Modifier.isvolatile (pengubah int);
Selain itu, kami juga bisa mendapatkan antarmuka yang diimplementasikan oleh kelas induk
// Dapatkan kelas antarmuka [] kelas = superclass.getInterfaces (); System.out.println ("Antarmuka kelas induk" + kelas [0]);Karena kelas Java dapat menerapkan banyak antarmuka, mereka menggunakan array, tetapi ketika benar -benar menggunakannya, Anda harus terlebih dahulu menentukan panjang array.
Di bawah ini, kami akan fokus untuk menjelaskan konten yang terdaftar di atas.
Konstruktor
Menggunakan Refleksi Java, Anda bisa mendapatkan konstruktor kelas, dan secara dinamis membuat objek saat runtime berdasarkan konstruktor. Pertama, Java memperoleh contoh konstruktor dengan:
// constructorconstructor [] constructors = exampleObjectClass.getConstructors (); untuk (konstruktor konstruktor: konstruktor) {System.out.println (konstruktor.toString ()); }Hasilnya adalah sebagai berikut:
PUBLIK CN.BYHIEG.REFLECTIONTUTORIAL.EXAMPLEOBJECT (INT, JAVA.LANG.InTEGER) PUBLIK CN.BYHIEG.REFLECTIONTUTORIAL.EXAMPLEOBJECT (JAVA.LANG.STRING) PUBLIK.
Jika Anda tahu jenis parameter konstruktor yang akan diakses terlebih dahulu, Anda dapat menggunakan metode berikut untuk mendapatkan konstruktor yang ditentukan, sebagai berikut:
Constructor constructor = exampleObjectClass.getConstructor (String.class); System.out.println (constructor.tostring ());
Hasilnya jelas:
public cn.byhieg.reflectiontutorial.ExampleObject(java.lang.String)
Konstruktor lain juga dapat diperoleh dengan cara berikut
Constructor constructor = exampleObjectClass.getConstructor (int.class, integer.class); System.out.println (constructor.tostring ());
Selain itu, jika kita tidak tahu parameter konstruktor dan hanya bisa mendapatkan semua objek konstruktor, kita dapat memperoleh parameter yang digunakan setiap konstruktor sebagai berikut:
Konstruktor [] konstruktor = exampleObjectclass.getConstructors (); untuk (konstruktor konstruktor: konstruktor) {class [] parameterTypes = constructor.getParametertypes (); System.out.println ("Parameter konstruktor adalah sebagai mengikuti ==================================================================== ======================================================================== untuk (class clz: parameterTypes) {System.out.println ("ParameterType" + clz.toString ());Hasilnya adalah sebagai berikut:
Parameter konstruktor adalah sebagai berikut ================================== Parameter Jenis kelas java.lang.Lang.String Parameter Konstruktor adalah sebagai berikut =========================== Paramer Parameter Paramer.
Di sini, dapat dilihat bahwa metode konstruksi tanpa parameter tidak mencetak hasilnya. Objek kelas dari tipe dasar dan objek kelas dari jenis referensi berbeda.
Sekarang, suatu objek dapat dibuat secara dinamis berdasarkan berbagai informasi dari konstruktor.
Objek objek = konstruktor.newinstance (1.100); System.out.println (Object.ToString ());
Ada dua kondisi untuk membuat objek. Yang pertama dibuat melalui konstruktor parameter. Yang kedua adalah bahwa objek konstruktor harus diperoleh melalui getConstructor yang lulus dalam informasi parameter.
Kondisi pertama adalah bahwa untuk objek yang dapat dibuat tanpa metode konstruksi parameter, tidak perlu mendapatkan objek konstruktor. Objek kelas memanggil metode newinstance () dan membuat objek secara langsung.
Kondisi kedua adalah bahwa objek konstruktor harus diperoleh melalui formulir ExampeObjectClass.getConstructor (String.class); Akan salah untuk mendapatkan array konstruktor melalui getConstructors dan kemudian memanggil objek konstruktor yang ditentukan untuk membuat objek di JDK1.8. Tapi JDK1.6 normal.
variabel
Menggunakan Refleksi Java, Anda bisa mendapatkan informasi variabel dari kelas saat runtime, dan Anda dapat membuat objek dan mengatur nilai variabelnya sesuai dengan metode di atas. Pertama, semua variabel publik diperoleh dengan mengikuti metode berikut:
Bidang [] Fields = exampleObjectClass.getFields (); untuk (bidang bidang: bidang) {System.out.println ("Variabel adalah:" + field.toString ()); }Hasilnya adalah sebagai berikut:
Variabelnya adalah: int cn.byhieg.reflectiontutorial.exampleObject.age Variabelnya adalah: public java.lang.string cn.byhieg.reflectiontutorial.exampleObject.name
Jelas, semua variabel publik yang diperoleh bersifat publik, dan skor variabel swasta di atas tidak diperoleh.
Cara yang sama dengan konstruktor diperoleh, kami dapat menentukan nama parameter dan kemudian mendapatkan variabel yang ditentukan:
Bidang bidang = exampleObjectClass.getField ("usia"); System.out.println ("Variabel adalah:" + field.toString ());Nama yang diperoleh dengan metode tostring dari variabel di atas terlalu panjang. Java menyediakan metode getName ke kelas lapangan, yang mengembalikan nama variabel yang ditulis di kelas. Kode di atas dapat diubah ke field.getName ().
Refleksi tidak hanya menyediakan cara untuk mendapatkan variabel, tetapi juga menyediakan cara untuk menetapkan nilai variabel. Dengan mengikuti metode berikut, Anda dapat mengubah nilai variabel dari kelas yang dihasilkan secara dinamis:
ExampleObject object = ((exampleObject) constructor1.newInstance ("ByHieg")); System.out.println ("Usia asli adalah" + Object.age); field.set (objek, 10); System.out.println ("Usia setelah perubahan adalah" + Object.age);Hasilnya adalah sebagai berikut:
Usia asli adalah 30 dan usia setelah perubahan adalah 10
Menurut kode di atas, Anda bisa mendapatkan objek bidang bernama usia, kemudian panggil metode yang ditetapkan objek, berikan objek dan nilai yang akan diubah, dan kemudian Anda dapat mengubah nilai objek. Perhatikan bahwa metode ini tidak hanya berguna untuk variabel anggota, tetapi juga untuk variabel statis. Tentu saja, jika itu adalah variabel statis, tidak apa -apa untuk melewati nol tanpa melewati objek.
metode
Selain memberi kami informasi variabel kelas, Refleksi Java juga memberi kami informasi metode. Refleksi memungkinkan kita untuk mendapatkan nama metode, parameter metode, tipe pengembalian metode, dan metode panggilan.
Pertama, dapatkan metode melalui kode berikut:
// Metode publik dari metode kelas output [] Metode = ExposeObjectClass.getMethods (); untuk (metode metode: metode) {System.out.println ("Method ="+ Method.getName ()); }Kode yang terlihat akrab seperti mendapatkan variabel. GetName dipanggil langsung di sini untuk mendapatkan nama metode yang ditulis di kelas. Setelah menulis ini, Anda harus secara alami berpikir bahwa Java juga menyediakan metode khusus berdasarkan parameter.
Metode metode = exampleObjectclass.getMethod ("setage", int.class); System.out.println (method.getName ());Perbedaannya di sini adalah bahwa metode getMethod juga perlu meneruskan informasi tipe parameter, yang mencerminkan menyediakan metode untuk mendapatkan parameter metode dan jenis pengembalian. Contoh memperoleh parameter metode adalah sebagai berikut:
Metode metode = exampleObjectclass.getMethod ("setage", int.class); System.out.println (method.getName ()); untuk (kelas clz: method.getParameterTypes ()) {System.out.println ("Parameter metode" + clz.getName ()); }Hasilnya adalah sebagai berikut:
Parameter int dari metode setage
Contoh mendapatkan tipe pengembalian metode adalah sebagai berikut:
System.out.println(method.getReturnType().getName());
Hasilnya adalah sebagai berikut:
void
Selain itu, refleksi Java mendukung metode yang diperoleh melalui panggilan invoke. Contohnya adalah sebagai berikut:
method.invoke(exampleObjectClass.newInstance(),1);
Parameter pertama Invoke adalah objek ini, dan parameter kedua adalah array panjang variabel, dan parameter metode dilewatkan. Seperti objek bidang, untuk metode statis, Anda dapat melewati metode statis nol dan memanggil.
Variabel pribadi dan metode pribadi
Metode di atas hanya dapat memperoleh metode dan variabel publik, tetapi tidak dapat memperoleh metode dan variabel yang dimodifikasi non-publik. Java menyediakan metode tambahan untuk mendapatkan variabel dan metode non-publik. Artinya, variabel dan metode pribadi diperoleh melalui metode getDeclared dan metode GetDeclaredMethods. Ini juga mendukung penggunaan getDeclaredfield (nama variabel) dan getDeclaredMethod (nama metode) untuk mendapatkan nama variabel dan nama metode yang ditentukan. Namun, objek bidang dan objek metode yang diperoleh dengan cara ini tidak dapat digunakan secara langsung. Objek -objek ini harus disebut setAccessible (true) untuk penggunaan normal. Metode berikut dapat sama seperti yang disebutkan di atas.
anotasi
Pertama tulis kelas yang berisi anotasi:
@MyAnnotation (name = "ByHieg", value = "Hello World") Public Class AnnotationObject {@myannotation (name = "field", value = "variable") bidang string publik; @Myannotation (name = "Method", value = "Method") public void dosomething () {System.out.println ("Do Something"); } public void dootherthing (@myannotation (name = "param", value = "param") string param) {}}@retensi (retentionPolicy.runtime) public @interface myannotation {public string name (); nilai string publik ();}Java memberi kami informasi tentang mendapatkan anotasi kelas saat runtime, dan kami bisa mendapatkan anotasi kelas, anotasi metode, anotasi parameter, dan anotasi variabel.
Seperti metode akuisisi di atas, Java menyediakan dua metode akuisisi. Salah satunya adalah mendapatkan semua anotasi dan mengembalikan array, dan yang kedua adalah menentukan anotasi yang ditentukan.
Mari kita ambil anotasi kelas sebagai contoh untuk menjelaskan dua cara perolehan berikut.
Kelas clz = annotationObject.class; Anotasi [] anotasi = clz.getAnnotations (); Anotasi anotasi = clz.getAnnotation (annotationObject.class);
Kemudian, pemrosesan selanjutnya dapat dilakukan berdasarkan anotasi yang diperoleh. Berikut ini adalah contoh pemrosesan:
untuk (anotasi anotasi: anotasi) {if (instance annotation dari myannotation) {myannotation myannotation = (myannotation) anotasi; System.out.println ("Nama:" + myannotation.name ()); System.out.println ("Value:" + Myannotation.Value ()); }}Anotasi kelas di atas diperoleh dengan memanggil getAnnotations menggunakan objek kelas. Anotasi metode dan anotasi variabel adalah sama. Saya menyebut getDeclaredAnnotations menggunakan objek metode dan objek lapangan masing -masing untuk mendapatkan anotasi. Saya tidak punya banyak hal untuk dikatakan. Lihat kode refleksi misalnya
Anotasi parameter adalah item yang relatif merepotkan. Metode akuisisi dibandingkan. Langkah pertama adalah mendapatkan objek metode terlebih dahulu dan hubungi getParameterAnnotations. Namun, nilai pengembalian ini adalah array dua dimensi, karena objek metode memiliki banyak parameter, dan setiap parameter mungkin memiliki banyak anotasi. Contohnya adalah sebagai berikut:
Metode metode1 = clz.getMethod ("dootherthing", string.class); Annotation [] [] annotationInparam = Method1.getParameterAnnotations (); Class [] params = method1.getParametertypes (); int i = 0; untuk (anotasi [] anotasi: annotationInparam) {class para = params [i ++]; untuk (anotasi anotasi: anotasi) {if (instance annotation dari myannotation) {myannotation myannotation = (myannotation) anotasi; System.out.println ("Param:" + Para.getName ()); System.out.println ("Nama:" + myannotation.name ()); System.out.println ("Value:" + Myannotation.Value ()); }}}Generik
Karena java generik diimplementasikan melalui penghapusan, sulit untuk secara langsung mendapatkan informasi tentang jenis generik yang parameterisasi spesifik, tetapi kami dapat memperoleh informasi generik melalui formulir tidak langsung menggunakan refleksi. Misalnya, kelas berikut:
Daftar Public Class GenericObject {Public List <String>; Daftar Publik <String> getLists () {daftar kembali; } setLists public void (Daftar <String> daftar) {this.lists = daftar; }}Jika suatu metode mengembalikan kelas generik, kita dapat memanggil getGenericreturnType melalui objek metode untuk mendapatkanGenericreturnType untuk mendapatkan apa jenis parameterisasi spesifik dari kelas generik ini. Lihat kode berikut:
Kelas clz = genericObject.class; Metode metode = clz.getMethod ("getLists"); Ketik generictype = method.getGenericreturnType (); if (generictype instance dari parameterizedType) {parameterizedType parameterizedType = ((parameterizedType) generictype); Type [] type = parameterizedType.getActualTypearguments (); untuk (type type: type) {class aktualclz = ((class) type); System.out.println ("Jenis parameterisasi adalah:" + aktual); }}Hasilnya adalah sebagai berikut:
参数化类型为: class java.lang.String
Langkah -langkahnya agak rumit, jadi penjelasan berikut adalah:
Saya memang mendapatkan informasi spesifik tentang obat generik dengan melihat hasilnya.
Jika tidak ada metode yang mengembalikan tipe generik, maka kita juga dapat memperoleh tipe parameter dari tipe generik dengan parameter metode sebagai kelas generik, seperti metode setList di kelas di atas. Contohnya adalah sebagai berikut:
Metode setMethod = clz.getMethod ("setLists", list.class); Type [] genericparametertypes = setMethod.getGenericparametertypes (); untuk (type genericparametertype: genericparameterpes) {System.out.println ("GenericParametertypes adalah:" + genericparametertype.getTypeName ()); if (GenericParameterType instance dari parameterizedType) {parameterizedType parameterizedType = ((parameterizedType) genericParameterType); System.out.println ("ParameterizedType adalah:" + parameterizedType.getTypeName ()); Tipe tipe [] = parameterizedType.getActualTypearguments (); untuk (type type: type) {System.out.println ("Tipe parameterisasi adalah:" + ((kelas) type) .getName ()); }}}Hasil eksekusi adalah sebagai berikut:
GenericParametertypes adalah: java.util.list <java.lang.string> parameterisasiType adalah: java.util.list <java.lang.string> jenis parameterisasi adalah: java.lang.string
Karena parameter metode mungkin memiliki lebih dari satu jenis generik, kami mendapatkan GetGenericParametertypes untuk mendapatkan array, dan kami perlu menentukan apakah setiap elemen memiliki tipe parameter. Langkah -langkah selanjutnya mirip dengan yang di atas, jadi saya tidak akan banyak bicara.
Jika bahkan parameter metode tidak mengandung kelas generik, maka hanya kasus terakhir yang tersisa, melalui jenis variabel, yaitu, kelas bidang digunakan. Contohnya adalah sebagai berikut:
Bidang bidang = clz.getfield ("daftar"); Type type = field.getGenerictype (); if (type instance parameterizedType) {parameterizedType parameterizedType = ((parameterizedType) type); Type [] type = parameterizedType.getActualTypearguments (); untuk (type type1: type) {system.out.println ("Tipe parameterisasi:" + ((kelas) type1) .getTypeName ()); }}Prinsipnya sama seperti di atas, kecuali bahwa objek tipe adalah melalui field.getGenerictype (), jadi saya tidak akan mengatakan banyak tentang operasi yang tersisa.
Ini adalah pengantar untuk mendapatkan jenis generik yang parameter melalui refleksi.
Array
Refleksi Java dapat beroperasi pada array, termasuk membuat array, mengakses nilai dalam array, dan mendapatkan objek kelas dari suatu array.
Mari kita bicarakan secara sederhana, membuat array dan mengakses nilai -nilai dalam array: menggunakan kelas array dalam refleksi adalah yang di bawah paket refleksi.
// Buat array tipe int dengan panjang 3 int [] intarray = (int []) array.newinstance (int.class, 3); // Tetapkan nilai ke array melalui refleksi untuk (int i = 0; i <intarray.length; i ++) {array.set (intarray, i, i+2); } // array dalam bentuk refleksi, dapatkan nilai dalam array untuk (int i = 0; i <intarray.length; i ++) {System.out.println (array.get (intarray, i)); }Di atas adalah membuat array dan mengakses nilai -nilai dalam array menggunakan refleksi.
Untuk objek kelas yang mendapatkan array, Anda cukup menggunakan int []. Class , atau menggunakan class.forname, yang merupakan cara aneh untuk menulis:
Class clz = class.forname ("[i"); System.out.println (clz.gettypename ());Hasilnya adalah:
int[]
String dalam forname ini, [ mewakili array, saya mewakili int, float adalah f , double is d , dll. Jika Anda ingin mendapatkan array objek biasa, gunakan formulir berikut:
Class stringClz = Class.forName("[Ljava.lang.String;");
[ Katakanlah itu adalah array, sisi kanan L adalah nama kelas, dan sisi kanan tipe adalah A ; ;
Cara ini untuk mendapatkan objek kelas array terlalu rumit.
Setelah mendapatkan objek kelas array, beberapa metode uniknya dapat dipanggil, seperti memanggil getComponentType untuk mendapatkan informasi jenis anggota array. Misalnya, array int adalah tipe anggota, yang merupakan int.
System.out.println(clz.getComponentType().getTypeName());
Hasilnya adalah int
Meringkaskan
Kali ini, berbagai aplikasi refleksi berakhir dengan ini, dan mungkin ada penjelasan pengetahuan yang mendalam di masa depan. Untuk kode tertentu, Anda dapat melihat kode refleksi
Dalam paket SRC, ada berbagai kelas, dan di kelas tes, itu adalah akses ke kelas -kelas ini.
Di atas adalah semua konten artikel ini. Saya berharap konten artikel ini akan membantu untuk belajar atau bekerja semua orang. Saya juga berharap untuk mendukung wulin.com lebih lanjut!