您的位置:首页 > 其它

反射

2016-04-29 19:13 211 查看
  java中有一个Class类型,该类型的变量用于描述一个类或接口的结构信息,如通过Class类型的变量,可以获取其描述的类的名字,全部方法,属性…。

  A a = new A();
  //接口同样具有此特性
  Class c = a.getClass() = A.class


  java中的任何一个类型都能 . 出静态变量class,如类.class,接口.class,int.class,boolean.class。

  对于基本数据类型的类包装,不仅可以 . 出class,还可以 . 出TYPE,如Integer.TYPE,TYPE是一个Class类型的静态常量,Integer.class指的是Integer引用类型,Integer.TYPE指的是int基本类型。

//c可以描述任何一个引用类型的结构,?必须是引用类型。
Class<?> c
//c仅可以描述T类型的结构,T是泛型,实际指代何种类型,在程序运行后确定
Class<T> c
//c仅可以描述Student类型的结构
Class<Student> c
//c可以描述Student类型及其该类型的子类类型的结构
Class<? extends Student> c


  反射的本质就是通过,该类型的Class类型变量,来获取其描述的类型的各种信息,而后再做出相应的操作。

Class<Stident> c = Class.forName(“com.lnu.reflect.Student”);


  这一步完成的任务是,通过类的完全限定名,利用Class类的静态方法加载类到JVM,并返回已加载类的Class类型的变量。

  这种方式不需要import该类,但是工程目录下,或是classpath指定的路径下必须有该类,否则JVM找不到。

  通过c,可以获取加载的类Student的相关信息。

//获取类Student的全部访问修饰符为public的属性
Field[] fields = c.getFields();
//获取类Student的已经声明的全部属性
Field[] fields = c.getDeclaredFields();
//获取属性fields[i]的访问修饰符编码,返回的是int型的编码
int code = fields[i].getModifiers();
//返回编码对应的访问修饰符
Modifier.toString(code);
//返回属性fields[i]的类型的类类型变量
Class<?> field_class = field[i].getType();
//返回属性fields[i]的名字
String name = fields[i].getName();
//获取类Student的全部访问修饰符为public的方法
Method[] methods = c.getMethods();
//获取类Student的已经声明的全部方法
Method[] methods = c.getDeclaredMethods();
//返回方法的访问修饰符,名字同上
//返回方法的返回类型的类类型变量使用getReturnType()
//返回方法的全部参数的类型的类类型变量
getParameterTypes()


  前面通过forName方法加载了类,并通过c获取到了加载的类的各种信息,现在要想使用这些信息,必须要先实例化一个该类的实例,然后才可以使用。

Object obj = c.newInstance();
Class<?> params_classes =
{参数1的Class类型变量,参数2的Class类型变量...};


  方法参数的Class类型变量数组,注意一个类或接口的Class类型变量只有一个,Class类型变量就是对应这个类,这个类的所有对象都是共享这个类的Class类型的变量。

//根据方法的名字和方法的参数的类型的Class类型变量的数组获取方法
Method method = c.getDeclaredMethod(“方法的名字”, params);
//方法的参数变量值数组
Object[] params_values = {参数1,参数2,…};
//设置方法的执行权限,使其可以执行私有方法
method.setAccessible(true);
//执行方法,需要给出执行方法的类的实例和方法的参数变量值数组
method.invoke(obj, params_values);
//根据属性的名字返回指定的属性
Field field = c.getDeclaredField(“属性名”);
//设置属性的访问权限,使其可以访问私有属性
field.setAccessible(true);
//获取类的实例obj的属性field的值
field.get(obj);
//设置类的实例obj的属性field的值为value
field.set(obj, value);

public class ReflectTest {
public static void main(String[] args) {
Class<?> c = null;
try {
//加载类,要用类的完全限定名,返回加载类的Class类型的变量
c = Class.forName("com.lnu.reflect.example.Student");
//获取类的公共属性信息,getDeclaredFields()是获取全部属性
System.out.println("=====获取类的公共属性信息=====");
Field[] public_properties = c.getFields();
for(int i = 0; i < public_properties.length; i++) {
System.out.println("属性访问修饰符:" +
Modifier.toString(public_properties[i]
.getModifiers()));
System.out.println("属性类型的类类型变量:" +
public_properties[i].getType());
System.out.println("属性名:" +
public_properties[i].getName());
System.out.println();
}
//获取此类的公共方法信息,这包括子类继承的公共方法
System.out.println("=====获取类的公共方法信息=====");
Method[] public_methoda = c.getMethods();
for(int i = 0; i < public_methoda.length; i++) {
System.out.println("方法访问修饰符:" +
Modifier.toString(public_methoda[i]
.getModifiers()));
System.out.println("方法返回值类型的类类型变量:" +
public_methoda[i].getReturnType());
System.out.println("方法名:" +
public_methoda[i].getName());
//返回方法参数的类型的类类型变量
for(int j = 0; j < public_methoda[i]
.getParameterTypes().length; j++) {
System.out.println("方法的参数" + (int)(j + 1) +
"的类型的类类型变量:%s" + (public_methoda[i]
.getParameterTypes())[j]);
}
System.out.println();
}
//获取此类的全部方法信息,不包括此类继承的方法
//输出的方法顺序未必就是类中定义的方法的顺序
//由此调用方法时,必须知道方法的名字
System.out.println("=====获取类的全部方法信息=====");
Method[] all_methoda = c.getDeclaredMethods();
for(int i = 0; i < all_methoda.length; i++) {
//操作同上
}
System.out.println("=====执行类的某个方法=====");
//实例化此类的一个对象,看newInstance()方法的源代码可以发现,方法
//定义的返回类型是T,即是一个泛型,只有在实际用时才会知道T代表什么类
型,在此我们创建Class的变量c所指代的类型的一个实例
Object obj = c.newInstance();
//创建此方法的参数的类型的类类型变量数组
Class<?>[] param_types = {String.class, Integer.TYPE};
//根据方法的名字和方法参数的类型的类类型变量数组获取方法
Method method = c.getDeclaredMethod("say_4",
param_types);
//创建执行方法的参数变量值数组
Object[] param_values = {"test", 1};
//设置方法的执行权限,使其可以执行私有的方法
method.setAccessible(true);
//调用此方法,参数为方法所属的对象以及执行方法所需要的参数值数组
String return_result = (String)method
.invoke(obj, param_values);
System.out.println("方法的返回值:" + return_result);
System.out.println("==返回类的某个属性值,并重新赋值==");
Field field = c.getDeclaredField("message");
field.setAccessible(true);
String field_value = (String)field.get(obj);
System.out.println("属性message的值:" + field_value);
field.set(obj, "I am a student");
String field_value_modified = (String)field.get(obj);
System.out.println("重新赋值后的属性message的值:" +
field_value_modified);
} catch (Exception e) {
System.out.println("ReflectionTest " + e.toString());
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: