Posted on 2006-04-14 17:02
Terry的Blog 閱讀(1940)
評(píng)論(0) 編輯 收藏 所屬分類(lèi):
java語(yǔ)言
Reflection是Java的一個(gè)重要特性。這種機(jī)制可以讓我們通過(guò)類(lèi)名,方法名,數(shù)據(jù)成員名來(lái)得到相關(guān)的元素。
關(guān)鍵類(lèi)java.lang.Class:這個(gè)也是Object的子類(lèi) 是利用反射機(jī)制的起點(diǎn)。
1:產(chǎn)生Class object
使用getClass()
String str = "abc";
Class c1 = str.getClass();
使用Class.getSuperclass();
Button b = new Button();
Class c1 = b.getClass();
Class c2 = c1.getSuperclass();
使用static method Class.forName()
Class c1 = Class.forName ("java.lang.String");
Class c2 = Class.forName ("java.awt.Button");
Class c3 = Class.forName ("java.util.LinkedList$Entry");
使用 類(lèi)名.class
Class c1 = String.class;
Class c2 = java.awt.Button.class;
Class c3 = Main.InnerClass.class;
Class c4 = int.class;
Class c5 = int[].class;
使用primitive wrapper classes的TYPE
Class c1 = Boolean.TYPE;
Class c2 = Byte.TYPE;
Class c3 = Character.TYPE;
Class c4 = Short.TYPE;
Class c5 = Integer.TYPE;
Class c6 = Long.TYPE;
Class c7 = Float.TYPE;
Class c8 = Double.TYPE;
Class c9 = Void.TYPE;
2:使用
Class object
package
reflection;

import
java.lang.reflect.Constructor;
import
java.lang.reflect.Field;
import
java.lang.reflect.Method;
import
java.lang.reflect.Modifier;
import
java.util.HashMap;


public
class
TestRef
{


public
static
void
main(String[] args)
throws
Exception
{
TestRef testRef
=
new
TestRef();
Class clazz
=
TestRef.
class
;
System.out.println(
"
getPackage() =
"
+
clazz.getPackage().getName());
//
getModifiers()的返回值可以包含類(lèi)的種類(lèi)信息。比如是否為public,abstract,static
int
mod
=
clazz.getModifiers();
System.out.println(
"
Modifier.isAbstract(mod) =
"
+
Modifier.isAbstract(mod));
System.out.println(
"
getName() =
"
+
clazz.getName());
System.out.println(
"
getSuperclass() =
"
+
clazz.getSuperclass().getName());
System.out.println(
"
getInterfaces() =
"
+
clazz.getInterfaces());
//
實(shí)現(xiàn)了哪些Interface
System.out.println(
"
clazz.getDeclaredClasses() =
"
+
clazz.getDeclaredClasses());
//
包含哪些內(nèi)部類(lèi)
System.out.println(
"
getDeclaringClass() =
"
+
clazz.getDeclaringClass());
//
如果clazz是inner class 那么返回其outer class
System.out.println(
"
----------
"
);
Constructor[] constructor
=
clazz.getDeclaredConstructors();
//
返回一組構(gòu)造函數(shù) Constructor[]
if
(constructor
!=
null
)
{

for
(
int
i
=
0
; i
<
constructor.length; i
++
)
{
System.out.println(constructor[i].getName());
}
}
System.out.println(
"
----------
"
);
Method[] method
=
clazz.getDeclaredMethods();
//
Method[]
if
(method
!=
null
)
{

for
(
int
i
=
0
; i
<
method.length; i
++
)
{
System.out.println(method[i].getName());
}
}
System.out.println(
"
----------
"
);
Field[] field
=
clazz.getDeclaredFields();
//
Field[]
if
(field
!=
null
)
{

for
(
int
i
=
0
; i
<
field.length; i
++
)
{
System.out.println(field[i].getName());
System.out.println(field[i].getType().getName());
System.out.println(field[i].get(testRef));
}
}
//
動(dòng)態(tài)生成instance(無(wú)參數(shù))
Class clz
=
Class.forName(
"
reflection.TestRef
"
);
Object obj
=
clz.newInstance();
System.out.println(((TestRef)obj).getStr());
//
動(dòng)態(tài)生成instance(有參數(shù))
Class[] params
=
new
Class[]
{String.
class
,
int
.
class
,
double
.
class
}
;
Constructor construct
=
clz.getConstructor(params);
//
JDK1.5的情況下可以直接用{"haha",999,100.01}作為參數(shù)
Object obj2
=
construct.newInstance(
new
Object[]
{
"
haha
"
,
new
Integer(
999
),
new
Double(
100.01
)}
);
System.out.println(((TestRef)obj2).getStr());
//
動(dòng)態(tài)調(diào)用method(public method)
Class[] params2
=
new
Class[]
{String.
class
}
;
Method methods
=
clz.getMethod(
"
setStr
"
, params2);

methods.invoke(testRef,
new
Object[]
{
"
invoke method
"
}
);
System.out.println(testRef.getStr());
//
動(dòng)態(tài)改變field內(nèi)容(public field)
Field fields
=
clz.getField(
"
str
"
);
fields.set(testRef,
"
set field's value
"
);
System.out.println(testRef.getStr());
}
public
TestRef()
{
System.out.println(
"
--- complete TestRef() ---
"
);
}

public
TestRef(String str,
int
i,
double
d)
{
this
.str
=
str;
this
.i
=
i;
this
.d
=
d;
System.out.println(
"
--- complete TestRef(String str, int i, double d) ---
"
);
}
public
String str
=
"
I'm a string
"
;

int
i
=
1
;

double
d
=
3.14
;

HashMap map
=
new
HashMap();


public
double
getD()
{
return
d;
}
public
void
setD(
double
d)
{
this
.d
=
d;
}
public
int
getI()
{
return
i;
}
public
void
setI(
int
i)
{
this
.i
=
i;
}
public
HashMap getMap()
{
return
map;
}
public
void
setMap(HashMap map)
{
this
.map
=
map;
}
public
String getStr()
{
return
str;
}
public
void
setStr(String str)
{
this
.str
=
str;
}
}
3說(shuō)明:
上面代碼的運(yùn)行環(huán)境是JDK1.4.2_08
動(dòng)態(tài)得到方法getMethod()和動(dòng)態(tài)得到數(shù)據(jù)成員getField()時(shí)要求訪問(wèn)級(jí)別是public的。但是相應(yīng)的getDeclaredMethods() 和getDeclaredFields()可以得到private的元素。
4補(bǔ)充:
public class ReflectSecurity {
public static void main(String[] args) {
try {
TwoString ts = new TwoString("a", "b");
Field field = clas.getDeclaredField("m_s1");
// field.setAccessible(true);
System.out.println("Retrieved value is " + field.get(inst));
} catch (Exception ex) {
ex.printStackTrace(System.out);
}
}
}
如果我們編譯這一程序時(shí),不使用任何特定參數(shù)直接從命令行運(yùn)行,它將在field.get(inst)調(diào)用中拋出一個(gè)Class異常。
如果我們不注釋field.setAccessible
(true)代碼行,那么重新編譯并重新運(yùn)行該代碼,它將運(yùn)行成功。
最
后,如果我們?cè)诿钚刑砑恿薐VM參數(shù) -Djava.security.manager
以實(shí)現(xiàn)安全性管理器,它仍然將不能通過(guò)運(yùn)行,會(huì)拋出java.security.AccessControlException,除非我們定義了
ReflectSecurity類(lèi)的許可權(quán)限。