一:Class類的使用
1: Class 類介紹
? ? 在Java中除了基本數(shù)據(jù)類型和靜態(tài)的東西都是對象,都是Java.lang.class的對象,

? ? 在上面的Code我們創(chuàng)建了一個Food類,實例化了一個food的對象, 其實Food這個類也是一個對象,是Java.lang.class的對象 。我們知道,通過new A(A任意一個類)來得到一個A類的對象,同樣任意一個類都是class的對象,我們也可以獲取到Class的對象
? ? 獲方式如下:
? ? ? ? ? 1:Class c1 = Food.class()
? ? ? ? ? 2:? Class c2 = food.getClass();
? ? ? ? ? ? 3: Classc3 = Class.forName(“com.xxx.xx”);

2:動態(tài)加載類
? ? ? 程序都分為編譯期和運行期2個時期。
? ? ? 編譯期:是指編譯器將源代碼翻譯為機器能識別的代碼,java為編譯為jvm認識的字節(jié)碼文件。?
? ? ? 運行期:則是指java代碼的運行過程。

? ? ? ? 在我們的FactoryFood中,我們需要根據(jù)實際情況引很多個類,而且我們需要編譯期編譯很多類,但實際可能只會用到1,2個類。

? ? ? 在我們的DynamicFactory中,我們沒有引入任何實體類,而是由程序動態(tài)的加載和創(chuàng)建對象。需要什么類就傳入什么類的包.類名即可
總結(jié):通過動態(tài)加載類的方式,我們可以隨意的添加和刪除類而不需要重新編譯。然而靜態(tài)類卻不行,每次新增類都需要重新編譯程序。
二:獲取方法信息
? ? 下面讓我們通過反射的方式來獲取類的名稱,方法,變量,函數(shù)的參數(shù),返回值

? ? getMethods():獲取所有的public方法,包括從父類繼承過來的,如上面的wait方法(在java中我們新建的類默認繼承Object,所以Food類里面就獲取到了warit方法)

? ? getDeclareMethods():獲取類自己申明的方法包括(public, private, protect)通過上面的輸出我們可以看出來,使用getDeclareMethods獲取到了updateFood(private)但是沒有獲取到wait(從父類繼承的)
三:獲取成員變量
? ? 前面我們介紹了方法的獲取方法,那成員變量依然可以獲取,而且成員變量也是對象是Java.lang.Field的對象,
? ? 我們先在類中添加一個public Character character的成員變量
? ? 下面演示獲取成員變量信息的例子

? ? getFields()只能獲取public的成員變量,在輸出信息中,我們可以看到只輸出了一個character的成員變量
? ? getDeclareField()可以獲取該類所有自己聲明的成員變量包括public的,private的和protected,以及default類型的
四:獲取構(gòu)造函數(shù)信息
? ? 類是對象,成員變量是對象,同樣構(gòu)造函數(shù)也是對象,是Java.lang.Constructor的對象。
? ? 下面讓我們來獲取構(gòu)造函數(shù)的參數(shù)列表和參數(shù)類型

? ? getConstructors():獲取所有的public的構(gòu)造函數(shù)(也有private的構(gòu)造函數(shù),比如:單例模式中就存在)
? ? getDeclareConstructors():獲取所有自己申明的構(gòu)造函數(shù)(構(gòu)造函數(shù)只能是自己申明的)
? ? 同樣我們也可以通過getInterface, getSuperClass獲取接口和父類

? ? 注:只要我們得到類的類型,我們就可以得到該類的所有信息
五:方法的反射
? ? 前面講述了一大堆獲取方法,變量,參數(shù),返回值的操作,接下來就來實際操作通過反射來調(diào)用我們的方法,指令method.invoke();
? ? 首先,我們要調(diào)用方法就要先獲取方法信息,要獲取方法信息就要獲取類信息,就是獲取類類型
? ? 首先我們在Food類中添加如下三個方法:

? ? 然后我們來反射調(diào)用這三個方法:

? ? 在上面的code中,我們先調(diào)用setDefaultName來給Food命名,然后在調(diào)用getFoodName來檢查我們是否成功的通過反射完成了設(shè)值,然后我們再調(diào)用有參數(shù)的方法setFoodNumber,來重新設(shè)置name和 number然后再調(diào)用getFoodName來檢查我們是否成功的通過反射完成了設(shè)值

? ? 從輸出的信息,我么可以得知我們成功的通過反射來完成了Food方法的調(diào)用,但是我們發(fā)現(xiàn),第一次的輸出是null,因為我們的第一次調(diào)用的函數(shù)是無返回值的。
? ? 注:當(dāng)有返回值,Object為具體的返回值,無返回值時,Object為null函數(shù)有參數(shù)時,調(diào)用時傳入具體的參數(shù),多個參數(shù),傳入一個Object數(shù)組;無參數(shù)調(diào)用時不傳參數(shù)
深入理解:
? ? 反射是編譯之后的操作,前面的文章我們講泛型,說泛型是編譯期的安全檢查,那我們就可以通過反射來給泛型插入數(shù)據(jù)而不出現(xiàn)編譯錯誤:


? ? 通過上面的輸出結(jié)果我們可以發(fā)現(xiàn)我們定義了String的ArrayList,添加了一個”First”,這時候size是1,然后又通過反射來添加一個22到ArrayList中,輸出的 Size是2。所以通過反射可以繞過泛型的檢查(因為編譯器在編譯期會做泛型擦除)。