JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
先看一下反射的概念:
主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。
反射是java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高!
看概念很晕的,继续往下看。
反射机制的作用:
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的方法
在这里先看一下sun为我们提供了那些反射机制中的类:
java.lang.Class;
java.lang.reflect.Constructor; java.lang.reflect.Field;
java.lang.reflect.Method;
java.lang.reflect.Modifier;
class 类
具体实现
使用java的反射机制,一般需要遵循三步:
-
- 获得你想操作类的Class对象
- 通过第一步获得的Class对象去取得操作类的方法或是属性名
- 操作第二步取得的方法或是属性
Java运行的时候,某个类无论生成多少个对象,他们都会对应同一个Class对象,它表示正在运行程序中的类和接口。如何取得操作类的Class对象,常用的有三种方式:
-
- 调用Class的静态方法forName,如上例;
- 使用类的.class语法,如:Class<?> cls = String.class;
- 调用对象的getClass方法,如:String str = "abc";Class<?> cls = str .getClass();
public class Employee {
public Employee(){
name = "nick";
age = 25;
}
String name="";
int age=0;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
1,反射机制获取类有三种方法,我们来获取Employee的Class类
//第一种方式:
Class c1 = Class.forName("package.xxx.Employee"); //完整的路径名
//第二种方式:
//java中每个类型都有class 属性.
Class c2 = Employee.class;
//第三种方式:
//java语言中任何一个java对象都有getClass 方法
Employee e = new Employee();
Class c3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee)
注意 Employee若是内部类,这类名前为$号,而不是“.”
Class c =Class.forName("com.jd.wxsq.jzcircle.bean.Employee");
//创建此Class 对象所表示的类的一个新实例
Object o = c.newInstance(); //调用了Employee的无参数构造方法.
注意,若获取内部类构造方法时,需要将其外部类的类对象作为参数传进去
Constructor constructor = c.getDeclaredConstructor(new Class[] {
Out.class });
同样实例化内部类时,也需要将外部类对象作为参数传进去
obj = constructor.newInstance(new Out());
3, 获取属性:分为所有的属性和指定的属性:
//获取所有的属性?
Field[] fs = c.getDeclaredFields();
//定义可变长的字符串,用来存储属性
StringBuffer sb = new StringBuffer();
//通过追加的方法,将每个属性拼接到此字符串中
//最外边的public定义
sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() +"{\n");
//里边的每一个属性
for(Field field:fs){
sb.append("\t");//空格
sb.append(Modifier.toString(field.getModifiers())+" ");//获得属性的修饰符,例如public,static等等
sb.append(field.getType().getSimpleName() + " ");//属性的类型的名字
sb.append(field.getName()+";\n");//属性的名字+回车
}
sb.append("}");
由打印信息我们可以看到能够获取到Employee的所以成员。
//获取特定的“name"属性
Field f = c.getDeclaredField("name");
//使用反射机制可以打破封装性,导致了java对象的属性不安全,设置可访问
f.setAccessible(true);
//给o对象的name属性赋值
f.set(o,"Join");
通过上面方法我们可以获取指定的属性,并改变它的值。
//获取特定的setAge方法,Integer.TYPE为其对应的形参数类型
Method method = c.getDeclaredMethod("setAge",Integer.TYPE);
//调用特定的setAge方法,若为静态方法,则invoke的第一个参数为null
method.invoke(o,100);