java中反射的三種方法

java中反射的三種方法:
1. 通過Object類的getClass方法來獲取
java.lang.Object中定義有getClass方法:public final Class getClass()
所有Java對象都具備這個方法,該方法用於返回調用該方法的對象的所屬類關聯的Class對象,例如:
Date date1 = new Date();  
Date date2 = new Date();  
Class c1 = date1.getClass();  
Class c2 = date2.getClass();  
System.out.println(c1.getName()); 
// java.util.Date  
System.out.println(c1 == c2); 
// true  
上面的代碼中,調用Date對象date1的getClass方法將返回用於封裝Date類信息的Class對象。
這裏調用了Class類的getName方法:public String getName(),這個方法的含義很直觀,即返回所封裝的類的名稱。
需要注意的是,代碼中的date1和date2的getClass方法返回了相同的Class對象(c1==c2的值爲true)。這是因爲,對於相同的類,JVM只會載入一次,而與該類對應的Class對象也只會存在一個,無論該類實例化了多少對象。
另外,需要強調的是,當一個對象被其父類的引用或其實現的接口類型的引用所指向時,getClass方法返回的是與對象實際所屬類關聯的Class對象。例如:
List list = new ArrayList();  
System.out.println(list.getClass().getName()); // java.util.ArrayList  
上面的代碼中,語句list.getClass()方法返回的是list所指向對象實際所屬類java.util.ArrayList對應的 Class對象而並未java.util.List所對應的Class對象。有些時候可以通過這個方法瞭解一個對象的運行時類型,例如:
HashSet set = new HashSet();  
Iterator it = set.iterator();  
System.out.println(it.getClass().getName()); //java.util.HashMap$KeyIterator  
從代碼可以看出,HashSet的iterator方法返回的是實現了Iterator接口的HashMap內部類(KeyIterator)對象。
因爲抽象類和接口不可能實例化對象,因此不能通過Object的getClass方法獲得與抽象類和接口關聯的Class對象。
2. 使用.class的方式
使用類名加“.class”的方式即會返回與該類對應的Class對象。例如:
Class clazz = String.class;  
System.out.println(clazz.getName()); // java.lang.String  
這個方法可以直接獲得與指定類關聯的Class對象,而並不需要有該類的對象存在。
3. 使用Class.forName方法
Class有一個著名的static方法forName:public static Class forName(String className) throws ClassNotFoundException
該方法可以根據字符串參數所指定的類名獲取與該類關聯的Class對象。如果該類還沒有被裝入,該方法會將該類裝入JVM。
該方法聲明拋出ClassNotFoundException異常。顧名思義,當該方法無法獲取需要裝入的類時(例如,在當前類路徑中不存在這個類),就會拋出這個異常。
例如,如果當前類路徑中存在Foo類:
package org.whatisjava.reflect;  
public class Foo {  
    public Foo() {  
        System.out.println("Foo()");  
    }  
    static {  
        System.out.println("Foo is initialized");  
    }  
}  
運行下面的代碼:
Class clazz = Class.forName("org.whatisjava.reflect.Foo");
控制檯會有如下輸出:
Foo is initialized
Class.forName("org.whatisjava.reflect.Foo")首先會將reflection.Foo類裝入JVM,並返回與之關聯的Class對象。JVM裝入Foo類後對其進行初始化,調用了其static塊中的代碼。需要注意的是:forName方法的參數是類的完 整限定名(即包含包名)。
 區別於前面兩種獲取Class對象的方法:使用Class.forName方法所要獲取的與之對應的Class對象的類可以通過字符串的方式給定。該方法通常用於在程序運行時根據類名動態的載入該類並獲得與之對應的Class對象。
通過上面的文章相信你對java的反射機制有了一定的認識,同時也對java中Class類的用法有了比較清晰的理解,在我們實際工作的過程中,我們不斷的運用java知識來解決實際生活中的問題的時候我們就能對java反射機制有一個更深入的理解!

二、代碼示例
1.ClassTest.java

[java] view plaincopy
/** 
 * java中Class類的使用 
 */  
import java.io.*;  
import java.lang.reflect.*;  
public class ClassTest1 {  
    public ClassTest1(){  
          
    }  
    public static void main(String[] args) throws Exception{  
        ClassTest1 test=new ClassTest1();  
        ClassTest1 test1=test.getClass().newInstance();  
        //test1=test;  
        test.printMessage();  
        test1.printMessage();  
        System.out.println(test.hashCode());  
        System.out.println(test1.hashCode());  
          
        Method[] method=test1.getClass().getMethods();  
          
        for(Method m :method){  
            System.out.println(m.getDeclaringClass());  
            System.out.println(m.getName());  
        }  
    }  
    public void printMessage(){  
        System.out.println("Created successful!");  
    }  
}  
運行結果:

[plain] view plaincopy
Created successful!  
Created successful!  
14576877  
12677476  
class ClassTest1  
printMessage  
class ClassTest1  
main  
class java.lang.Object  
wait  
class java.lang.Object  
wait  
class java.lang.Object  
wait  
class java.lang.Object  
hashCode  
class java.lang.Object  
getClass  
class java.lang.Object  
equals  
class java.lang.Object  
toString  
class java.lang.Object  
notify  
class java.lang.Object  
notifyAll  
2.TestClass.java 

[java] view plaincopy
/** 
 *  
 */  
public class TestClass {  
    public static void main(String[] args)  
    {  
        try {  
            // 測試Class.forName()  
            Class testTypeForName = Class.forName("TestClassType");  
            System.out.println("testForName---" + testTypeForName);  
            // 測試類名.class  
            Class testTypeClass = TestClassType.class;  
            System.out.println("testTypeClass---" + testTypeClass);  
            // 測試Object.getClass()  
            TestClassType testGetClass = new TestClassType();  
            System.out.println("testGetClass---" + testGetClass.getClass());  
        } catch (ClassNotFoundException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
    }  
}  
  
class TestClassType {  
    // 構造函數  
    public TestClassType() {  
        System.out.println("----構造函數---");  
    }  
    // 靜態的參數初始化  
    static {  
        System.out.println("---靜態的參數初始化---");  
    }  
    // 非靜態的參數初始化  
    {  
        System.out.println("----非靜態的參數初始化---");  
    }  
}  
運行結果:
[plain] view plaincopy
---靜態的參數初始化---  
testForName---class TestClassType  
testTypeClass---class TestClassType  
----非靜態的參數初始化---  
----構造函數---  
testGetClass---class TestClassType  
分析:根據結果可以發現,三種生成的Class對象一樣的,並且三種生成Class對象只打印一次“靜態的參數初始化”。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章