Posted on 2006-04-14 17:02
Terry的Blog 閱讀(1940)
評論(0) 編輯 收藏 所屬分類:
java語言
Reflection是Java的一個重要特性。這種機制可以讓我們通過類名,方法名,數據成員名來得到相關的元素。
關鍵類java.lang.Class:這個也是Object的子類 是利用反射機制的起點。
1:產生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");
使用 類名.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()的返回值可以包含類的種類信息。比如是否為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());
//
實現了哪些Interface
System.out.println(
"
clazz.getDeclaredClasses() =
"
+
clazz.getDeclaredClasses());
//
包含哪些內部類
System.out.println(
"
getDeclaringClass() =
"
+
clazz.getDeclaringClass());
//
如果clazz是inner class 那么返回其outer class
System.out.println(
"
----------
"
);
Constructor[] constructor
=
clazz.getDeclaredConstructors();
//
返回一組構造函數 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));
}
}
//
動態生成instance(無參數)
Class clz
=
Class.forName(
"
reflection.TestRef
"
);
Object obj
=
clz.newInstance();
System.out.println(((TestRef)obj).getStr());
//
動態生成instance(有參數)
Class[] params
=
new
Class[]
{String.
class
,
int
.
class
,
double
.
class
}
;
Constructor construct
=
clz.getConstructor(params);
//
JDK1.5的情況下可以直接用{"haha",999,100.01}作為參數
Object obj2
=
construct.newInstance(
new
Object[]
{
"
haha
"
,
new
Integer(
999
),
new
Double(
100.01
)}
);
System.out.println(((TestRef)obj2).getStr());
//
動態調用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());
//
動態改變field內容(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說明:
上面代碼的運行環境是JDK1.4.2_08
動態得到方法getMethod()和動態得到數據成員getField()時要求訪問級別是public的。但是相應的getDeclaredMethods() 和getDeclaredFields()可以得到private的元素。
4補充:
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);
}
}
}
如果我們編譯這一程序時,不使用任何特定參數直接從命令行運行,它將在field.get(inst)調用中拋出一個Class異常。
如果我們不注釋field.setAccessible
(true)代碼行,那么重新編譯并重新運行該代碼,它將運行成功。
最
后,如果我們在命令行添加了JVM參數 -Djava.security.manager
以實現安全性管理器,它仍然將不能通過運行,會拋出java.security.AccessControlException,除非我們定義了
ReflectSecurity類的許可權限。