Posted on 2006-04-14 17:02
Terry的Blog 阅读(1932)
评论(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类的许可权限。