反射(Reflection)能够让运行于 JVM 中的程序检测和修改运行时的行为
反射就是把Java类中的各种成分通过java的反射API映射成相应的Java类,得到这些类以后就可以对其进行使用。比如方法,构造方法,成员变量,类型,包等。
反射的基本方法
在java.lang.reflect包中有三个重要的类:
● Field:描述类的域(成员变量)
● Method:描述类的方法(方法)
● Constructor:描述类的构造器(构造器)
对于public域(包括超类成员):
● getFields
● getMethods
● getConstructors
对于其它域(包括私有和受保护的成员,不包括超类成员):
● gettDeclaredFields
● gettDeclaredMethods
● gettDeclaredConstructors
获取Class三种方式
//1.类名.class
Class pc1 = Person.class;
//2.对象名.getClass()
Class pc2 = person.getClass();
//3.Class.forName("类名")
Class pc3 = null;
其中,跟反射密切相关的就是forName这个方法,通过类名去获取字节码。前面两种都是虚拟机中已经加载过了。forName方法在当虚拟机中没有加载过对应字节码的时候,就会去动态地加载进来;当已经加载过的时候,直接复用加载过的。
//暴力破解私有权限
constructor.setAccessible(true);
例子
public class Person {
public String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("name:"+name);
System.out.println("age:"+age);
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void fun(String name) {
System.out.println("name==============="+name);
}
private void fun_private(String name) {
System.out.println("fun_private___name==========="+name);
}
}
public static void main(String[] args) throws IllegalAccessException, InstantiationException {
Person person = new Person("name:Coco", 22);
//获取Class三种方式
//1.类名.class
Class pc1 = Person.class;
//2.对象名.getClass()
Class pc2 = person.getClass();
//3.Class.forName("类名")
Class pc3 = null;
try {
pc3 = Class.forName("com.bwie.reflectdemo1.reflect.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//获取无参构造函数,并实例化类
try {
Constructor constructor = pc1.getDeclaredConstructor(null);
//setAccessible是启用和禁用访问安全检查的开关,并不是为true就能访问为false就不能访问
// constructor.setAccessible(true);
Person person1 = (Person) constructor.newInstance(null);
person1.fun(person.name);
} catch (Exception e) {
e.printStackTrace();
}
//获取有参构造方法,并实例话
try {
Constructor constructor = pc2.getConstructor(new Class[]{String.class, int.class});
Person person2 = (Person) constructor.newInstance("Coco一米八", 22);
person2.fun(person2.name);
} catch (Exception e) {
e.printStackTrace();
}
//获取私有方法
//Declared获取私有的受保护的,不包括超类成员
try {
//获取私有的方法传入方法名和class
Method method = pc3.getDeclaredMethod("fun_private", String.class);
method.setAccessible(true);
//调用传入实例,和参数
method.invoke(pc3.newInstance(), "Coco获取私有");
} catch (Exception e) {
e.printStackTrace();
}
//获取成员变量
try {
Person person1 = (Person) pc1.newInstance();
Field age = pc1.getDeclaredField("age");
age.setAccessible(true);
age.set(person1,22);
//属性获取传入对象
System.out.println(person1.getAge()+"---"+age.get(person1));
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
打印结果
name:name:Coco
age:22
name===============name:Coco
name:Coco一米八
age:22
name===============Coco一米八
fun_private___name===========Coco获取私有
22---22