1. 程式人生 > >Class對象和反射

Class對象和反射

運行 無法 類庫 靜態塊 化工 integer 第一個 額外 般的

1.class對象
在java中一切都是對象,從某種意義上,java中的對象可以分為:實例對象和Class對象。實例對象通過new關鍵得到,那麽Class對象呢?Class對象無法通過new關鍵字獲取,在類加載的過程中,JVM生成一個與加載的字節碼文件相關的class對象。通過類名可以獲取對應Class對象。class對象主要用來對應類的所有對象。java程序在運行之前並未完全加載,各個類只在需要的時候才將該類加載進內存,生成對應的class對象。

所有的類都是在對其第一次使用的時候,動態加載到JVM中,當程序創建第一個對類靜態成員的引用的時候,就會加載這個。使用new創建類的對象的也會被當做是對類靜態成員的引用。因此java程序在它開始運行之前並非被完全加載,其各個部分是在必須的時候才加載。一旦某個類的Class對象被載入內存,它就用來創建這個類的所有的對象。如下面程序所示:

 1 class Test1{
 2     static{
 3         System.out.println("loading1");
 4     }
 5     
 6 }
 7 class Test2{
 8     static{
 9         System.out.println("loading2");
10     }
11     
12 }
13 class Test3{
14     static{
15         System.out.println("loading3");
16     }
17     
18 }
19 public class
Demo { 20 public static void main(String[] args) { 21 //new Test1(); 22 Class clz = Test1.class;//註意Class clz = Test1.class;,不會觸發靜態塊的執行,即不會自動初始化該Class對象 23 try { 24 25 Class.forName("Test2"); 26 } catch (ClassNotFoundException e) { 27 e.printStackTrace();
28 } 29 new Test3(); 30 } 31 32 }

輸出結果:

loading1
loading2
loading3

2.Class對象的獲取

Class對象是jvm用來保存對象實例對象的相關信息的,除此之外,我們完全可以把Class對象看成一般的實例對象,事實上所有的Class對象都是類Class的實例。獲取Class對象主要有三種方式:

 1 /**      
 2 *    獲取Class對象的三種方式    
 3 */
 4 public class Demo{
 5     public static void main(String[] args){
 6         //1.通過實例對象獲取class對象
 7         Demo demo = new Demo();
 8         Class clsdemo = demo.getClass();
 9         
10         //2.通過Class的靜態方法forName
11         try {
12             Class clsdemo2 = Class.forName("Demo");
13         } catch (ClassNotFoundException e) {
14             e.printStackTrace();
15         }
16         
17         //3.通過類名和class關鍵字獲取
18         Class clsdemo3 = Demo.class;
19     }
20 }

3.Class對象的使用和反射
JAVA反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱為java語言的反射機制。通過反射機制來訪問一個類java對象的屬性,方法,甚至我們可以輕易改變一個私有成員。java反射是基於Class類和java.lang.Reflect類庫。反射機制使得我們可以創建一個編譯時完全未知的對象,並調用這個對象的方法。

 1 public class Demo{
 2     public static void main(String[] args){
 3         
 4         Test test = new Test();
 5         System.out.println(test.getClass()==Test.class);//一個類對應的class對象在內存中是唯一的
 6         
 7         Class cls = Test.class;//字節碼文件加載進內存,生成class對象,但是不會進行相關的初始化工作,不引起靜態塊的執行
 8         try {
 9             
10             Field [] fields = cls.getDeclaredFields();
11             for (Field field : fields) {
12                 System.out.println(field);
13             }
14             Method [] methods = cls.getDeclaredMethods();
15             for (Method method : methods) {
16                 System.out.println(method);
17             }
18         } catch (SecurityException e) {
19             e.printStackTrace();
20         }
21     }
22 }
23 class Test{
24     public static int count=0;
25     private int age=20;
26     public String name="xm";
27     static{
28         System.out.println("類被加載");
29     }
30     public void test(){
31         System.out.println("sss");
32     }
33     private void call(){
34         System.out.println("hi");
35     }
36 }
類被加載
true
public static int com.test.demo.Test.count
private int com.test.demo.Test.age
public java.lang.String com.test.demo.Test.name
public void com.test.demo.Test.test()
private void com.test.demo.Test.call()

4.泛化的Class引用

Class引用總是指向某個Class對象,它可以制造實例,並包含可以作用於這些實例的所有方法代碼,且包含該類的靜態成員,因此Class引用表示的就是它指向的對象的確切類型,而該對象便是Class類的一個對象。class引用可泛化。通過泛型語法,可以讓編譯器強制的執行額外的類型檢查。如果希望放松些限制,可以使用通配符?,表示“任何事物”,如Class<?> intClass = int.class;在java SE5中,Class<?>優於平凡的Class.如下:

public class Demo {
    public static void main(String[] args) {
        Class intClass = int.class;
        Class<Integer> integerClass = int.class;
        integerClass = Integer.class;
     Class<?> integerClz =
Integer.class;
} }

Class對象和反射