反射是什么
在创建一个对象的的时候会将他的字节码文件加载到方法区中,JVM会对字节码进行解剖,然后会创建一个对应的class对象,把字节码的全部信息加载进去,反射就是获取到class对象,然后使用字节码对象对该类的属性进行设置和方法的调用。
获取反射对象的方式
1 创建一个Person类
public class Person {
int id;
String name;
public Person(int id, String name) {
this.id = id;
this.name = name;
}
private Person(){}
private void sleep(){
System.out.println("sleep");
}
public void eat(){
System.out.println(name+"吃");
}
public static void sum(int[] arr){
System.out.println("arr length="+arr.length);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return name + id;
}
}
2 创建对象
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
Person person=new Person(110,"小明");
/*方式1 forName*/
Class<?> clazz1 = Class.forName("Person");
/*方式2 类名*/
Class<Person> clazz2 = Person.class;
/*方式3 通过对象获取*/
Class clazz3 = new Person().getClass();
}
}
3 获取构造方法
Constructor<?>[] declaredConstructors = person.getDeclaredConstructors(); //获取全部的构造方法
for (Constructor declaredConstructor:declaredConstructors){
System.out.println(declaredConstructor);
}
Constructor<?> declaredConstructor = person.getDeclaredConstructor(int.class, String.class);//获取单个指定构造方法
Object o = (Person)declaredConstructor.newInstance(999, "感冒灵");
System.out.println(o);
Constructor<?> declaredConstructor1 = person.getDeclaredConstructor(null);//获取私有构造函数
//暴力反射 获取权限 单例设计模式不推荐使用 会出现数据错乱
declaredConstructor1.setAccessible(true);
Person p1 = (Person) declaredConstructor1.newInstance(null);
System.out.println(p1);
4 获取执行方法
Method[] methods = person.getMethods();//获取所有的公共方法 包含父类的方法
Method[] declaredMethods = person.getDeclaredMethods();//获取所有的方法 不包含父类方法
Method eat = person.getMethod("eat", null);//获取到指定的方法
//执行方法
Person person1=new Person(1,"aa"); //创建对象
eat.invoke(person1,null); //1 方法的调用对象 2 方法所需要的参数
//执行私有方法
Method sleep = person.getDeclaredMethod("sleep", null);//获取私有方法
sleep.setAccessible(true);//获取访问权限
sleep.invoke(person1,null);
//sleep如果是静态方法 不需要对象来调用 就用sleep.invoke(null,null);调用
//参数为数组类型的方法
Method num = person.getMethod("sum", int[].class);
num.invoke(null,new int[]{2,9,0,88});