java中反射的三種方法:
1. 通過(guò)Object類的getClass方法來(lái)獲取
java.lang.Object中定義有g(shù)etClass方法:public final Class getClass()
所有Java對(duì)象都具備這個(gè)方法,該方法用于返回調(diào)用該方法的對(duì)象的所屬類關(guān)聯(lián)的Class對(duì)象,例如:
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
上面的代碼中,調(diào)用Date對(duì)象date1的getClass方法將返回用于封裝Date類信息的Class對(duì)象。
這里調(diào)用了Class類的getName方法:public String getName(),這個(gè)方法的含義很直觀,即返回所封裝的類的名稱。
需要注意的是,代碼中的date1和date2的getClass方法返回了相同的Class對(duì)象(c1==c2的值為true)。這是因?yàn)?,?duì)于相同的類,JVM只會(huì)載入一次,而與該類對(duì)應(yīng)的Class對(duì)象也只會(huì)存在一個(gè),無(wú)論該類實(shí)例化了多少對(duì)象。
另外,需要強(qiáng)調(diào)的是,當(dāng)一個(gè)對(duì)象被其父類的引用或其實(shí)現(xiàn)的接口類型的引用所指向時(shí),getClass方法返回的是與對(duì)象實(shí)際所屬類關(guān)聯(lián)的Class對(duì)象。例如:
List list = new ArrayList();
System.out.println(list.getClass().getName()); // java.util.ArrayList
上面的代碼中,語(yǔ)句list.getClass()方法返回的是list所指向?qū)ο髮?shí)際所屬類java.util.ArrayList對(duì)應(yīng)的 Class對(duì)象而并未java.util.List所對(duì)應(yīng)的Class對(duì)象。有些時(shí)候可以通過(guò)這個(gè)方法了解一個(gè)對(duì)象的運(yùn)行時(shí)類型,例如:
HashSet set = new HashSet();
Iterator it = set.iterator();
System.out.println(it.getClass().getName()); //java.util.HashMap$KeyIterator
從代碼可以看出,HashSet的iterator方法返回的是實(shí)現(xiàn)了Iterator接口的HashMap內(nèi)部類(KeyIterator)對(duì)象。
因?yàn)槌橄箢惡徒涌诓豢赡軐?shí)例化對(duì)象,因此不能通過(guò)Object的getClass方法獲得與抽象類和接口關(guān)聯(lián)的Class對(duì)象。
2. 使用.class的方式
使用類名加“.class”的方式即會(huì)返回與該類對(duì)應(yīng)的Class對(duì)象。例如:
Class clazz = String.class;
System.out.println(clazz.getName()); // java.lang.String
這個(gè)方法可以直接獲得與指定類關(guān)聯(lián)的Class對(duì)象,而并不需要有該類的對(duì)象存在。
3. 使用Class.forName方法
Class有一個(gè)著名的static方法forName:public static Class forName(String className) throws ClassNotFoundException
該方法可以根據(jù)字符串參數(shù)所指定的類名獲取與該類關(guān)聯(lián)的Class對(duì)象。如果該類還沒(méi)有被裝入,該方法會(huì)將該類裝入JVM。
該方法聲明拋出ClassNotFoundException異常。顧名思義,當(dāng)該方法無(wú)法獲取需要裝入的類時(shí)(例如,在當(dāng)前類路徑中不存在這個(gè)類),就會(huì)拋出這個(gè)異常。
例如,如果當(dāng)前類路徑中存在Foo類:
package org.whatisjava.reflect;
public class Foo {
public Foo() {
System.out.println("Foo()");
}
static {
System.out.println("Foo is initialized");
}
}
運(yùn)行下面的代碼:
Class clazz = Class.forName("org.whatisjava.reflect.Foo");
控制臺(tái)會(huì)有如下輸出:
Foo is initialized
Class.forName("org.whatisjava.reflect.Foo")首先會(huì)將reflection.Foo類裝入JVM,并返回與之關(guān)聯(lián)的Class對(duì)象。JVM裝入Foo類后對(duì)其進(jìn)行初始化,調(diào)用了其static塊中的代碼。需要注意的是:forName方法的參數(shù)是類的完 整限定名(即包含包名)。
區(qū)別于前面兩種獲取Class對(duì)象的方法:使用Class.forName方法所要獲取的與之對(duì)應(yīng)的Class對(duì)象的類可以通過(guò)字符串的方式給定。該方法通常用于在程序運(yùn)行時(shí)根據(jù)類名動(dòng)態(tài)的載入該類并獲得與之對(duì)應(yīng)的Class對(duì)象。
通過(guò)上面的文章相信你對(duì)java的反射機(jī)制有了一定的認(rèn)識(shí),同時(shí)也對(duì)java中Class類的用法有了比較清晰的理解,在我們實(shí)際工作的過(guò)程中,我們不斷的運(yùn)用java知識(shí)來(lái)解決實(shí)際生活中的問(wèn)題的時(shí)候我們就能對(duì)java反射機(jī)制有一個(gè)更深入的理解!
二、代碼示例
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!");
}
}
運(yùn)行結(jié)果:
[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 {
// 測(cè)試Class.forName()
Class testTypeForName = Class.forName("TestClassType");
System.out.println("testForName---" + testTypeForName);
// 測(cè)試類名.class
Class testTypeClass = TestClassType.class;
System.out.println("testTypeClass---" + testTypeClass);
// 測(cè)試Object.getClass()
TestClassType testGetClass = new TestClassType();
System.out.println("testGetClass---" + testGetClass.getClass());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class TestClassType {
// 構(gòu)造函數(shù)
public TestClassType() {
System.out.println("----構(gòu)造函數(shù)---");
}
// 靜態(tài)的參數(shù)初始化
static {
System.out.println("---靜態(tài)的參數(shù)初始化---");
}
// 非靜態(tài)的參數(shù)初始化
{
System.out.println("----非靜態(tài)的參數(shù)初始化---");
}
}
運(yùn)行結(jié)果:
[plain] view plaincopy
---靜態(tài)的參數(shù)初始化---
testForName---class TestClassType
testTypeClass---class TestClassType
----非靜態(tài)的參數(shù)初始化---
----構(gòu)造函數(shù)---
testGetClass---class TestClassType
分析:根據(jù)結(jié)果可以發(fā)現(xiàn),三種生成的Class對(duì)象一樣的,并且三種生成Class對(duì)象只打印一次“靜態(tài)的參數(shù)初始化”。
作者:傳智播客JavaEE培訓(xùn)學(xué)院
首發(fā):http://java.itcast.cn