JAVA 反射

来源:互联网 发布:java web log4j 编辑:程序博客网 时间:2024/04/27 11:33

   您查询的关键词是:newinstance object initargs  。如果打开速度慢,可以尝试快速版;如果想保存快照,可以添加到搜藏。
(百度和网页http://bbs.iaiai.com/forum/read.php?tid=2690的作者无关,不对其内容负责。百度快照谨为网络故障时之索引,不代表被搜索网站的即时页面。)

 主题 : java的反射机制  使用道具┊ 复制链接 ┊浏览器收藏┊打印

java的反射机制


java的反射机制一

在java里面有一种反射机制reflect,这是其它语言所没有的,可以动态创建对象和方法,还有成员变量等:

一.对象动态创建的方法如下:

我们需要使用的有Class类和Constructor类,还有Method和Field类,具体的使用方法如下:

1.使用Class类的Class.forName(String className)方法得到一个Class对象,

eg: Class aClass=Class.forName(Foo.class.getName());

或者 Class aClass=Class.forName("Foo");

2.得到一个Class对象之后,我们还需要把它转换成我们需要的类型对象,

eg: Foo foo=(Foo)aClass.newInstance();

注意此地方的newInstance()方法只能调用Foo类的公有无参构造函数,如果没有构造函数

则使用父类的公有无参构造函数,如果被重写了,则会创建对象失败。

3.得到了对象之后我们就可以任意摆布她了。

4.如果我们的构造函数里面需要传入参数,怎么办?

这时候我们就需要使用Constructor类了,创建方法如下:

eg: Constructor ctor = aClass.getDeclaredConstructor(Class[] parameterTypes);

如果我们有这样一个类需要动态创建对象:

public class BB {

private int baby = 9;

public BB(int b) {

baby = b;

}

/**

* @return Returns the baby.

*/

public int getBaby() {

return baby;

}

/**

* @param baby

* The baby to set.

*/

public void setBaby(int baby) {

this.baby = baby;

}

}

 

那么我们如何来做呢?

Integer[] os = new Integer[1];

os[0] = new Integer(6);

Class cls = Class.forName(BB.class.getName());

Constructor ctor = cls.getDeclaredConstructor((new Class[] { int.class }));

BB bbb = (BB) ctor.newInstance(os);

System.out.println(bbb.getBaby());

二.方法的动态创建:

假设上面的BB类需要动态创建getBaby()方法,我们该怎么做?这时候我们需要使用到

Method类了:

1.定义一个方法m:

eg: Class cls = Class.forName(BB.class.getName());

BB bb = (BB) cls.newInstance();

Method m = BB.class.getDeclaredMethod(/"getBaby/",null);

System.out.println(m.invoke(bb, null));

2.调用这个方法m.invoke(bb, null)。

3.上面是没有参数的方法的动态创建,如果我们需要动态的创建一个需要传入参数的方法,我们该

怎么做呢?

eg: public class GG {

public String getS(int i) {

return /"hello baby/"+i;

}

public static void main(String[] args) {

System.out.println(/"I'm a gg!/");

}

}

我们可以这么做:

Integer[] os = new Integer[1];

os[0] = new Integer(6);

Class cls = Class.forName(GG.class.getName());

GG bb = (GG) cls.newInstance();

Method m = GG.class.getDeclaredMethod(/"getS/",(new Class[] { int.class }));

String s = (String) m.invoke(bb, os);

System.out.println(s);

4.从上面的学习中,你已经掌握了基本的对象和方法的创建技巧,我下面介绍如何来动态创建main方法:

eg: String[] os = new String[1];

Class cls = Class.forName(GG.class.getName());

GG bb = (GG) cls.newInstance();

Method m = GG.class.getDeclaredMethod(/"main/",(new Class[] { os.getClass()}));

m.invoke(bb, new Object[] {new String[]{/"Hello baby!/"}});

Ok,祝贺你成功了!

三.成员变量的动态创建:

如果我们需要动态的创建一个成员变量,我们该怎么做呢?这时候我们就需要使用Field类了,

比如,我们把GG类修改一下,代码如下:

public class GG {

public String name = /"I'm GG/";

public String getS(int i) {

return /"hello baby/" + i;

}

public static void main(String[] args) {

System.out.println(args[0] + /" I'm gg!/");

}

}

1.我们需要动态创建成员变量name,并取出他的初始值,可以按照下面的步骤来做:

Class cls = Class.forName(GG.class.getName());

GG bb = (GG) cls.newInstance();

Field field=GG.class.getDeclaredField(/"name/");

System.out.println(field.get(bb));

需要注意的地方是field.get(bb),里面要传入对象bb。

2.如果我们需要给这个成员变量赋值,我们可以这么做:

Class cls = Class.forName(GG.class.getName());

GG bb = (GG) cls.newInstance();

Field field=GG.class.getDeclaredField(/"name/");

field.set(bb,/"Hello Baby!/");

System.out.println(field.get(bb)); 

昙花绽放之后便期待下一次盛开,惊涛骇浪的爱情之后,心海在沉寂中涌动,而情到深处的人是孤独的。

java的反射机制二


四.通过上面的学习,你基本上就可以去做一般的应用了,我们在这里还看一下她们的API,

看看还有什么好东西:

1.共有下面几种创建Constructor的方法:

Constructor getConstructor(Class[] params) -- 获得使用特殊的参数类型的公共构造函数,

Constructor[] getConstructors() -- 获得类的所有公共构造函数

Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数类型的构造函数(与接入级别无关)

Constructor[] getDeclaredConstructors() -- 获得类的所有构造函数(与接入级别无关)

2.Constructor共有下面几种方法:
boolean
equals(Object obj)
Compares this Constructor against the specified object.

Class
getDeclaringClass()
Returns the Class object representing the class that declares the constructor represented by this Constructor object.

Class[]
getExceptionTypes()
Returns an array of Class objects that represent the types of of exceptions declared to be thrown by the underlying constructor represented by this Constructor object.

int
getModifiers()
Returns the Java language modifiers for the constructor represented by this Constructor object, as an integer.

String
getName()
Returns the name of this constructor, as a string.

Class[]
getParameterTypes()
Returns an array of Class objects that represent the formal parameter types, in declaration order, of the constructor represented by this Constructor object.

int
hashCode()
Returns a hashcode for this Constructor.

Object
newInstance(Object[] initargs)
Uses the constructor represented by this Constructor object to create and initialize a new instance of the constructor's declaring class, with the specified initialization parameters.

String
toString()
Returns a string describing this Constructor

3.共有下面几种创建Field的方法:

Field getField(String name) -- 获得命名的公共字段

Field[] getFields() -- 获得类的所有公共字段

Field getDeclaredField(String name) -- 获得类声明的命名的字段

Field[] getDeclaredFields() -- 获得类声明的所有字段 

昙花绽放之后便期待下一次盛开,惊涛骇浪的爱情之后,心海在沉寂中涌动,而情到深处的人是孤独的。

回复 引用 举报顶端 

水季 离线
  

级别: 总版主
  

显示用户信息  UID: 2
精华: 16
发帖: 4008
铜币: 6 枚
威望: 4421 点
贡献值: 0 点
银元: 0 个
在线时间: 445(时)
注册时间: 2005-12-30
最后登录: 2009-12-31  板凳  发表于: 2006-06-30    只看该作者 ┊  小 中 大
java的反射机制三


4.Field共有下面几种方法:

boolean
equals(Object obj)
Compares this Field against the specified object.

Object
get(Object obj)
Returns the value of the field represented by this Field, on the specified object.

boolean
getBoolean(Object obj)
Gets the value of a static or instance boolean field.

byte
getByte(Object obj)
Gets the value of a static or instance byte field.

char
getChar(Object obj)
Gets the value of a static or instance field of type char or of another primitive type convertible to type char via a widening conversion.

Class
getDeclaringClass()
Returns the Class object representing the class or interface that declares the field represented by this Field object.

double
getDouble(Object obj)
Gets the value of a static or instance field of type double or of another primitive type convertible to type double via a widening conversion.

float
getFloat(Object obj)
Gets the value of a static or instance field of type float or of another primitive type convertible to type float via a widening conversion.

int
getInt(Object obj)
Gets the value of a static or instance field of type int or of another primitive type convertible to type int via a widening conversion.

long
getLong(Object obj)
Gets the value of a static or instance field of type long or of another primitive type convertible to type long via a widening conversion.

int
getModifiers()
Returns the Java language modifiers for the field represented by this Field object, as an integer.

String
getName()
Returns the name of the field represented by this Field object.

short
getShort(Object obj)
Gets the value of a static or instance field of type short or of another primitive type convertible to type short via a widening conversion.

Class
getType()
Returns a Class object that identifies the declared type for the field represented by this Field object.

int
hashCode()
Returns a hashcode for this Field.

void
set(Object obj, Object value)
Sets the field represented by this Field object on the specified object argument to the specified new value.

void
setBoolean(Object obj, boolean z)
Sets the value of a field as a boolean on the specified object.

void
setByte(Object obj, byte b)
Sets the value of a field as a byte on the specified object.

void
setChar(Object obj, char c)
Sets the value of a field as a char on the specified object.

void
setDouble(Object obj, double d)
Sets the value of a field as a double on the specified object.

void
setFloat(Object obj, float f)
Sets the value of a field as a float on the specified object.

void
setInt(Object obj, int i)
Sets the value of a field as an int on the specified object.

void
setLong(Object obj, long l)
Sets the value of a field as a long on the specified object.

void
setShort(Object obj, short s)
Sets the value of a field as a short on the specified object.

String
toString()
Returns a string describing this Field. 

昙花绽放之后便期待下一次盛开,惊涛骇浪的爱情之后,心海在沉寂中涌动,而情到深处的人是孤独的。

java的反射机制四


5.共有下面几种创建Method的方法:

Method getMethod(String name, Class[] params) -- 使用特定的参数类型,获得命名的公共方法

Method[] getMethods() -- 获得类的所有公共方法

Method getDeclaredMethod(String name, Class[] params) -- 使用特写的参数类型,获得类声明的命名的方法

Method[] getDeclaredMethods() -- 获得类声明的所有方法

6.Method共有下面几种方法:
boolean
equals(Object obj)
Compares this Method against the specified object.

Class
getDeclaringClass()
Returns the Class object representing the class or interface that declares the method represented by this Method object.

Class[]
getExceptionTypes()
Returns an array of Class objects that represent the types of the exceptions declared to be thrown by the underlying method represented by this Method object.

int
getModifiers()
Returns the Java language modifiers for the method represented by this Method object, as an integer.

String
getName()
Returns the name of the method represented by this Method object, as a String.

Class[]
getParameterTypes()
Returns an array of Class objects that represent the formal parameter types, in declaration order, of the method represented by this Method object.

Class
getReturnType()
Returns a Class object that represents the formal return type of the method represented by this Method object.

int
hashCode()
Returns a hashcode for this Method.

Object
invoke(Object obj, Object[] args)
Invokes the underlying method represented by this Method object, on the specified object with the specified parameters.

String
toString()
Returns a string describing this Method

五.还有反射数组java.lang.reflect.Array,反射安全性java.lang.reflect.AccessibleObject和类加载器ClassLoader就比较偏了,这里暂不介绍。 

昙花绽放之后便期待下一次盛开,惊涛骇浪的爱情之后,心海在沉寂中涌动,而情到深处的人是孤独的。


java的反射机制五


如果我们要给一个类重新创建一个对象数组,我们该怎么做呢?

我们使用Field类,代码:

Class cls = Class.forName(GG.class.getName());

GG gg = (GG) cls.newInstance();

Field field = GG.class.getDeclaredField("clothes");

int[] clo=(int[])field.get(gg);

System.out.println(clo[1]);

GG类的代码为:

public class GG {

public String name = "I'm GG";

public int[] clothes = new int[6];

public GG() {

clothes[0] = 1;

clothes[1] = 2;

clothes[2] = 3;

clothes[3] = 4;

clothes[4] = 5;

clothes[5] = 6;

}

public String getS(int i) {

return "hello baby" + i;

}

public static void main(String[] args) {

System.out.println(args[0] + " I'm gg!");

}

}

如果我们需要给整型数组clothes增加长度到8,怎么办?

可以考虑下面代码:

Class cls = Class.forName(GG.class.getName());

GG gg = (GG) cls.newInstance();

Field field = GG.class.getDeclaredField("clothes");

int[] clo = (int[]) field.get(gg);

 

int size = 8;

 

Class type = clo.getClass().getComponentType();

Object o = Array.newInstance(type, size);

System

.arraycopy(clo, 0, o, 0, Math.min(Array.getLength(clo),

size));

field.set(gg, o);

这里使用了反射数组java.lang.reflect.Array;使用反射数组之后我们可以不用知道数组的类型而直接进行扩充。

在处理反射时安全性是一个较复杂的问题。反射经常由框架型代码使用,由于这一点,您可能希望框架能够全面接入您的代码,无需考虑常规的接入限制。但是,在其它情况下,不受控制的接入会带来严重的安全性风险,如当代码在不值得信任的代码共享的环境中运行时。

由于这些互相矛盾的需求,Java编程语言定义一种多级别方法来处理反射的安全性。基本模式是对反射实施与应用于源代码接入相同的的限制:

1. 从任意位置到类公共组件的接入

2. 类自身外部无任何到私有组件的接入

3. 受保护和打包(缺省接入)组件的有限接入

不过-至少某些时候,围绕这些限制有一种简单的方法。我在前面实例中使用的Constructor、Field 和 Method 类都扩展了一个普通的基本类-- java.lang.reflect.AccessibleObject 类。该类定义一种setAccessible方法,使您能够启动或关闭对这些类中其中一个类的实例的接入检测。唯一的问题在于如果使用了安全性管理器,它将检测正在关闭接入检测的代码是否许可了这样做。如果未许可,安全性管理器抛出一个例外

看下面的代码:

public class GG {

public String name = "I'm GG";

}

public class Test1 {

public static void main(String[] args) {

try {

Class cls = Class.forName(GG.class.getName());

GG gg = (GG) cls.newInstance();

Field field = cls.getDeclaredField("name");

field.setAccessible(true);

System.out.println((String)field.get(gg));

} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}

如果你注释掉field.setAccessible(true)行之后可能就会抛出一个IllegalAccessException的异常。 

昙花绽放之后便期待下一次盛开,惊涛骇浪的爱情之后,心海在沉寂中涌动,而情到深处的人是孤独的。

 

 

原创粉丝点击