咱們在編寫JAVA程序的時候,建立一個對象JVM是怎樣來找到,理解並編譯到.class中的?那咱們就來看看在編譯中Class對象的偉大魅力;好了,廢話很少說,直接上乾貨:java
1: 首先,咱們來建立一個對象,方便咱們測試:數組
package entity; /** *@description TODO 測試對象 *@date 2018年1月1日 *@author geYang **/ public class Person { /** * 姓名 */ private String name; /** * 年齡 */ private int age; /** * 住址 */ private String address; public Person() { } public Person(String name, int age, String address) { this.name = name; this.age = age; this.address = address; } public static void printInfo(){ System.out.println("靜態方法調用"); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", address=" + address + "]"; } }
2: 測試Class的用法:ide
package reflex; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** *@description TODO Class類對象的簡單測試 *@date 2018年1月1日 *@author geYang **/ public class ClassTest { /** * 運行時類型信息使得咱們能夠在程序運行時發現和使用類型信息;而類型信息使咱們從只能在編譯期執行面向類型的操做的禁錮中解脫出來; * 而且可使用某些很是強大的程序; * * JAVA是如何讓程序在運行時識別對象和類的信息的.主要有兩種方法: * 1: "傳統的" RTTI : 它假定咱們在編譯時已經知道的須要的類型信息; * 2: "反 射" 機制 : 它容許咱們在運行時發現和使用類的信息; * * 注: 運行時類型識別(RTTI, Run-Time Type Identification)是Java中很是有用的機制 * ,在Java運行時,RTTI維護類的相關信息.多態(polymorphism)是基於RTTI實現的.RTTI的功能主要是由Class類實現的. * * Class 對象: * 要理解RTTI在JAVA中的工做原理,首先必須知道類型信息在運行時時如何表示的,這項工做是由稱爲Class對象的特殊對像完成的; * 事實上Class對象就是用來建立類的所用的"常規"對象的.Java使用Class對象來執行其RTTI; * 類是程序的一部分,每一個類都有一個Class對象.每當編寫或編譯一個新的類時都會產生一個新的對象(被保存在其.class文件中). * 爲了生成這個類的對象,運行這個程序的JVM將被稱爲"類加載器"的子系統; * 全部的類都是在對其第一次使用時,動態的加載到JVM中的.當程序建立第一個對類的靜態成員的引用時,就會加載這個類.這證實構造器也是類的靜態方法; * 即便沒有使用static,因此使用new操做符建立類的新對象也會被當作對類的靜態成員的引用; * 所以Java程序在其開始運行以前,並不是是被徹底加載,其各個部分是在必須時才加載的;動態加載也是Java的一大特性; * * 使用中類加載器首先檢查這個類的Class對象是否已經被加載.若是還沒有加載,默認的類加載器就會根據類名查找.class文件.這個類的字節碼被加載時, * 它們會接受驗證,以確保沒有被破壞;一擔某個類的Class被載入內存,它就會用來建立這個類的全部對象. * * 下面就來測試Class的用法: * @throws ClassNotFoundException * @throws SecurityException * @throws NoSuchFieldException * @throws NoSuchMethodException * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException * @throws InstantiationException **/ public static void main(String[] args) throws Exception { /* (舉個例子啊) 假設咱們當前並不知道String類是幹什麼的,但咱們只知道有 "java.lang.String" 這個名字,那麼怎麼來獲取String對象呢? */ //Class<?> clazz = Class.forName("java.lang.String"); //換成其餘也同樣 Class<?> clazz = Class.forName("entity.Person"); /* 要拋個找不到的錯,打印一下=>結果:"class java.lang.String" (沒有報錯)證實有這個類*/ System.out.println(clazz); /* 2,光有類也沒用,我還想看看他下面有什麼屬性 */ System.out.println("================= 全部屬性 ====================="); Field[] fields = clazz.getDeclaredFields(); //獲取到一個 Field 對象的數組(證實,類中的屬性也都是一個對象),打印一下: for(Field field : fields){ System.out.println(field); } System.out.println("================= 單一屬性 ============="); Field field = clazz.getDeclaredField("name"); System.out.println(field); /* 3,獲取類的方法 */ System.out.println("================= 全部方法 ====================="); Method[] methods = clazz.getDeclaredMethods(); for(Method method : methods){ System.out.println(method); } System.out.println("========= 單一方法(無參) ========="); Method method = clazz.getDeclaredMethod("getName", new Class[]{}); System.out.println(method); System.out.println("========= 單一方法(有參) ========="); Method method2 = clazz.getDeclaredMethod("setName", new Class[]{String.class}); System.out.println(method2); /* 3,獲取類的構造器 */ System.out.println("================= 全部構造器 ====================="); Constructor<?>[] constructors = clazz.getDeclaredConstructors(); for(Constructor<?> constructor : constructors){ System.out.println(constructor); } System.out.println("======== 單一構造器(無參) ======="); Constructor<?> constructor = clazz.getDeclaredConstructor(new Class[]{}); System.out.println(constructor); System.out.println("======== 單一構造器(有參) ======="); Constructor<?> constructor2 = clazz.getDeclaredConstructor(new Class[]{String.class,int.class,String.class}); System.out.println(constructor2); /*4, 根據類的的構造器來獲取對象*/ System.out.println("================= 對象(無參) ====================="); Object object = constructor.newInstance(new Object[]{}); System.out.println(object); System.out.println("================= 對象(有參) ====================="); Object object2 = constructor2.newInstance(new Object[]{"張三",18,"綿陽"}); System.out.println(object2); } }
作了上面的測試,那麼對於Class對象已經有了初步的瞭解;測試
參考: https://ke.qq.com/course/180327flex