如果我們要在程序運行時動態(tài)地加載某個類,我們應該如何做呢?將要用到Reflection API,通過這種機制,我們可以而不知道類的名字,而得到類的所有函數(shù)的名字和類型,以及所有的數(shù)據(jù)成員的格式,而且,我們可以通過某些機制來動態(tài)的調(diào)用。通過Reflection API,可以實現(xiàn)強大的功能,就如同一個巨大的黑洞,可以接受一切東西,不管你是什么形態(tài)。事實上,編譯器,GUI,甚至是接口,都用到了Reflection。
Reflection的基本功能是什么呢?1.運行時生成類的實例(instance),2.執(zhí)行期間調(diào)用方法(Method),3.運行時修改數(shù)據(jù)成員(field)。
要實現(xiàn)這么強大的功能,首先必須了解Class類,Class在這里是單獨的一個類,它位于java.lang包中,它用以描述程序的接口和類等信息,它本身沒有構造函數(shù),但是可以通過以下三種方法獲得一個Class類的對象,它與某一個類或接口相關聯(lián)。
對于任何類的對象,可以通過 Class object=對象名.getClass()的方式,getClass()函數(shù)是Object類中的成員函數(shù)。
Class object=Class.forName(類名);forName()是Class類的一個靜態(tài)成員函數(shù)
通過Class object=類名.class語法,對于基本數(shù)據(jù)類型(Primitive)的封裝類,可以通過類名.TYPE語法,這一點比較特殊。
事實上,如果一個Class類的對象關聯(lián)了某一個類,那么可以通過Class類的成員newInstance()來利用關聯(lián)類的默認構造函數(shù)(即無參構造函數(shù))來聲明該類的一個對象。但是如果要調(diào)用帶參數(shù)的構造函數(shù),就要用到其他的方法。具體的步驟如下:
1.Class 對象與某類相關聯(lián)。
聲明用一個Class數(shù)組,(如parameter[])包含需要調(diào)用的構造函數(shù)所需要的參數(shù)類型信息
調(diào)用Class類的getConstrutor(parameter)來尋找合適的構造函數(shù),把他的值返回給一個Construtor的對象(此處設為cons),Constructor類在java.lang.reflect包下,需要單獨加載。
聲明一個Object類的對象數(shù)組(此處設為 arg[]),這是實際參數(shù)。
利用cons.newInstance(arg),即可獲得一個對應類的對象。(該函數(shù)位于java.lang.reflect.Constructor類中)
動態(tài)調(diào)用成員函數(shù)的方法與之類似,不過對應的Constructor對象必須更改為一個Method類對象,Method類也在java.lang.reflect包中。它可以通過調(diào)用java.lang.reflect.Method類下的invoke(對象名,實參),形式調(diào)用某個函數(shù),這里并不需要聲明返回值,這一切交給JVM完成。它返回的值也是唯一確定的。
動態(tài)修改數(shù)據(jù)成員時,首先調(diào)用Class的getField()并指定field名稱。獲得特定的Field object之后便可直接調(diào)用Field的get()和set().
以下代碼除了動態(tài)調(diào)用函數(shù)和動態(tài)修改數(shù)據(jù)成員外,實現(xiàn)了全部本文提到的內(nèi)容,并在jdk1.5中運行通過。
import java.lang.reflect.*;
class ReflectTest
{
public static void main(String[] args)
{
if(args.length!=0)
{
Class flag=null;
try
{
flag=Class.forName(args[0]);
}
catch(Exception e)
{
e.printStackTrace();
}
Constructor[] cons=null;
try
{
cons=flag.getDeclaredConstructors();
}
catch(Exception e)
{
e.printStackTrace();
}
Method[] meth=null;
try
{
meth=flag.getDeclaredMethods();
}
catch(Exception e)
{
e.printStackTrace();
}
for(int i=0;i<cons.length;i++)
{
System.out.println(cons[i].getName());
}
for(int i=0;i<meth.length;i++)
{
System.out.println(meth[i].getName());
}
System.out.println("---------------------------");
Object o1=null;
try
{
o1=flag.newInstance();
}
catch(Exception e)
{
e.printStackTrace();
}
System.out.println(o1.toString());
Class[] parameters=new Class[]{String.class};
Constructor constr=null;
try
{
constr=flag.getConstructor(parameters);
}
catch(Exception e)
{
e.printStackTrace();
}
Object o2=null;
Object[] o3=new Object[]{"HongMei"};
try
{
o2=constr.newInstance(o3);
}
catch(Exception e)
{
e.printStackTrace();
}
System.out.println(o2);
}
else
{
System.out.println("We cant got parameter");
}
}
}
class Cigarette
{
static
{
System.out.println("Class Cigarette is loaded now");
}
Cigarette()
{
}
public Cigarette(String str)
{
this.logo=str;
}
public void smoke()
{
System.out.println("smoke feels good");
}
public void lighterType(String type)
{
System.out.println(type);
}
String logo;
public String toString()
{
return "Cigarette type is "+logo;
}
}
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1746387
posted on 2007-08-31 10:20
fly 閱讀(270)
評論(0) 編輯 收藏 所屬分類:
java學習