反射機制的定義:
在運行狀態時(動態的),對於任意一個類,都能夠得到這個類的所有屬性和方法。
對於任意一個對象,都能夠調用它的任意屬性和方法。
Class類是反射機制的起源,我們得到Class類對象有3種方法:
第一種:通過類名獲得
Class<?> class = ClassName.class;
第二種:通過類名全路徑獲得:
Class<?> class = Class.forName("類名全路徑");
第三種:通過實例對象獲得:
Class<?> class = object.getClass();
通過代碼總結三種方法的區別:
1 /** 2 * Created by hunt on 2017/6/23. 3 */ 4 5 /** 6 * 測試類 7 */ 8 public class ClassTest { 9 static{ 10 System.out.println("靜態代碼塊兒..."); 11 } 12 { 13 System.out.println("動態構造塊兒..."); 14 } 15 public ClassTest(){ 16 System.out.println("構造方法..."); 17 } 18 }
1 /** 2 * Created by hunt on 2017/6/23. 3 */ 4 5 /** 6 * 第一種方法獲得Class對象 7 */ 8 public class MainTest { 9 public static void main(String[] args) { 10 Class<?> calss = ClassTest.class; 11 } 12 } 13 14 /** 15 * 打印結果是: 16 * 什么都沒打印 17 * 說明ClassName.class不執行靜態塊和不執行動態塊兒 18 */
1 /** 2 * Created by hunt on 2017/6/23. 3 */ 4 5 /** 6 * 第二種方法獲得Class對象 7 */ 8 public class MainTest { 9 public static void main(String[] args) { 10 try { 11 Class<?> calss = Class.forName("com.souche.lease.admin.mytest.reflect.ClassTest"); 12 } catch (ClassNotFoundException e) { 13 e.printStackTrace(); 14 } 15 } 16 } 17 18 /** 19 * 打印結果是: 20 * 靜態代碼塊兒... 21 * 說明Class.forName("類名全路徑")執行靜態塊但是不執行動態塊兒(需要異常處理) 22 */
1 /** 2 * Created by hunt on 2017/6/23. 3 */ 4 5 /** 6 * 第三種方法獲得Class對象 7 */ 8 public class MainTest { 9 public static void main(String[] args) { 10 Class<?> calss = new ClassTest().getClass(); 11 } 12 } 13 14 /** 15 * 打印結果是: 16 * 靜態代碼塊兒... 17 動態構造塊兒... 18 構造方法... 19 * 說明對象.getClass()執行靜態塊也執行動態塊兒 20 */
總結:第一種方法:類字面常量使得創建Class對象的引用時不會自動地初始化該對象,而是按照之前提到的加載,鏈接,初始化三個步驟,這三個步驟是個懶加載的過程,不使用的時候就不加載。
第二種方法:Class類自帶的方法。
第三種方法:是所有的對象都能夠使用的方法,因為getClass()方法是Object類的方法,所有的類都繼承了Object,因此所有類的對象也都具有getClass()方法。
建議:使用類名.class,這樣做即簡單又安全,因為在編譯時就會受到檢查,因此不需要置於try語句塊中,並且它根除了對forName()方法的調用,所以也更高效。
注意:靜態塊僅在類加載時執行一次,若類已加載便不再重復執行;而動態構造塊在每次new對象時均會執行。