为什么要使用反射?
反射是动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,避免将程序写死到代码里,体现了多态的应用,可以降低类之间的藕合性。
例如: 实例化一个 person()对象, 不使用反射, new person(); 如果想变成 实例化 其他类, 那么必须修改源代码,并重新编译。使用反射: class.forName(“person”).newInstance(); 而且这个类描述可以写到配置文件中,如 **.xml, 这样如果想实例化其他类,只要修改配置文件的"类描述"就可以了,不需要重新修改代码并编译。
JAVA反射机制
是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
Class类实例表示正在运行的Java应用程序中的类和接口。Class是普通类、接口、枚举类、数组等的抽象,即它们的类型就是Class,它们是Class的实例。
既然Class代表着类和接口,那么我们可以通过他的实例(字节码文件)来获取对应类或接口的信息,如:注解、修饰符、类型、类的名称、属性、方法、构造方法、直接父类和子类等,还有可以创建它的实例,但只能调用无参构造方法来创建。
获取构造方法
getConstructors
getDeclaredConstructors
创建对象
newInstance()
con.newInstance(“zhangsan", 20);
获取所有成员
getFields,getDeclaredFields
获取单个成员
getField,getDeclaredField
修改成员的值
set(Object obj,Object value) 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
获取所有方法
getMethods
getDeclaredMethods
获取单个方法
getMethod
getDeclaredMethod
暴力访问
method.setAccessible(true);
反射获得当前值
public class Student {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getMethod(){
System.out.println("执行到了getMethod()");
return "得到了方法";
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
public class FansheClass {
public static void main(String[] args) throws Exception {
Student student = new Student();
student.setName("xzy");
student.setAge(10);
Class<? extends Student> class1 = student.getClass();
Class<? extends Student> student1 = class1;
// 输出 student1:class javazbzn.Student
Method[] declaredMethods = student1.getDeclaredMethods();
for (Method method : declaredMethods) {
// 输出类下所有的方法体
}
Field[] declaredFields = student1.getDeclaredFields();
for (Field field : declaredFields) {
// 输出类下所有的属性变量
String name = field.getName();
PropertyDescriptor descriptor = new PropertyDescriptor(name, student.getClass());
Method readMethod = descriptor.getReadMethod();
Object invoke = readMethod.invoke(student);
System.out.println(invoke);
// 输出xzy 和 10
}
}
}
反射参数使用
public class Main {
public static void main(String[] args) throws Exception{
//返回A的构造方法
Constructor c = A.class.getConstructor();
//返回A类的所有为public 声明的构造方法
Constructor[] cons = A.class.getConstructors();
//返回A类所有的构造方法,包括private
Constructor[] cons2 = A.class.getDeclaredConstructors();
//返回A类的第一个public 方法
Method m = A.class.getMethod(“say”);
//执行
m.invoke(A.class.newInstance(), null);
//返回A类所有的public 方法
Method[] ms = A.class.getMethods();
//返回A类所有的方法,包括private
Method[] allMs = A.class.getDeclaredMethods();
//返回A类的public字段
Field field = A.class.getField(“i”);
System.out.println(field.get(A.class.newInstance()));
//返回A类的static 字段
System.out.println(field.get(null));
}
}
class A{
public int i = 1;
public static int b = 2;
public A(){
System.out.println(“无参构造”);
}
private A(String s){
System.out.println(“有参构造”+s);
}
public void say(){
System.out.println("say");
}
}
通过class 类路径反射获得当前对象
1 public class Reflect{
2
3 public static void main(String[] args) throws Exception {
4
5 Class c1 = Class.forName(“com.test.job.Person”);
6
7 //创建此Class对象所表示类的一个新实例,
8 //newInstance方法调用的是Person的空参数构造方法
9 Object o = c1.newInstance();
10 System.out.println(o.toString());
11 }