什么是反射?
(反射通俗一点说就是把一个类里面的信息扒得赤裸裸的,一点都没有残余)
注意: 反射允许对成员变量,成员方法和构造方法的信息进行编程访问,我的理解:把反射当成为一个人,这个人可以把一个类里面的所有信息拿出来就是反射。在现实生活中经常用到反射,比如说idea中自动提示的功能其实就是利用反射实现的,还有就是idea中ctrl+p的提示功能也利用了反射。
反射分为两类:
- 获取:从class字节码文件中获取类中的所有信息
- 解剖:解剖要在获取的基础之上操作,先要获取才能得已解剖
获取class对象的三种方式: Class.forName("全类名"); 把.java文件变成.class文件(并没有加载到内存中) 源代码阶段 类名.class 加载到内存中 加载阶段 对象.getClass(); 运行阶段 创建对象new一个对象
反射获取构造方法:
Constrctor<?>[] getConstructors():返回所有公共构造方法对象的数组Constrctor<?>[] getDeclareConstructors():返回所有构造方法对象的数组Constrctor<T>[] getConstructor(Class<?>...parameterTypes):返回单个构造方法对象Constrctor<T>[] getDeclareConstructor(Class<?>...parameterTypes):返回单个构造方法对象
反射获取:
先创建一个实体类:
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name){
this.name=name;
}
protected Student(int age){
this.age=age;
}
private Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
再创建一个测试类(获取的东西都在代码可见):
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Parameter;
public class MyReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//1.获取class字节码文件对象
Class clazz = Class.forName("com.atguigu1.Student");
//获取了字节码文件之后,类中所有的内容都可以取出来
//2.获取构造方法
//获取所有
Constructor[] cons = clazz.getConstructors();
for (Constructor con : cons) {
System.out.println(con);
}
//获取所有
Constructor[] cons2 = clazz.getDeclaredConstructors();
for (Constructor con : cons2) {
System.out.println(con);
}
//获取单个
Constructor con1 = clazz.getDeclaredConstructor();
System.out.println(con1);
//获取单个(有参数)
Constructor con2 = clazz.getDeclaredConstructor(String.class);
System.out.println(con2);
//获取单个(有参数)
Constructor con3 = clazz.getDeclaredConstructor(int.class);
System.out.println(con3);
//获取两个参数的
Constructor con4 = clazz.getDeclaredConstructor(String.class, int.class);
System.out.println(con4);
//获取权限修饰符
int modifiers = con4.getModifiers();
System.out.println(modifiers);
//获取参数
Parameter[] parameters = con4.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter);
}
/*Student stu = (Student) con4.newInstance("张三", 23);
System.out.println(stu);
报错,虽然用了declare,但是也只是能够我们看到,不能使用,没有实际意义,如果要进行使用,需要进行暴力反射*/
//暴力反射:表示临时取消权限校验
con4.setAccessible(true);
Student stu = (Student) con4.newInstance("张三", 23);
System.out.println(stu);
}
}
反射获取成员变量:
与反射获取构造器大同小异,只是多出了
void set(Object obj,Object value):赋值
Pbject get(Object obj):获取值
反射获取成员方法:
与反射获取构造器大同小异,只是多了一点点东西:
Method类中用于创建对象的方法:
Object invoke(Object obj,Object... args):运行方法
- 参数一:用obj对象调用该方法
- 参数二:调用方法的传递的参数(如果没有就不写)
- 返回值:方法的返回值(如果没有就不写)
clazz.getMethods();//获取里面所有的的方法对象(包含父类中所有的公共的方法)
clazz.getDeclareMethods();//(不能获取父类的,但是可以获取本类中私有的)
clazz.getDeclareMethod("方法名",参数的字节码类型);//获取指定的单一方法
对象名.getExceptionTypes();//获取方法的抛出的异常
总结:
反射的作用
- 反射可获取一个类里面的所有的信息,获取到了之后,再执行其他的业务逻辑
- 反射可以结合配置文件,动态的创建对象并调用方法(好处就是不用修改代码,而直接修改配置文件)
- 反射获取构造方法、成员方法以及成员变量汇总:
| 方法名 | 行为 |
|---|---|
| get | 获取 |
| set | 设置 |
| Constructor | 构造方法 |
| Parameter | 参数 |
| Field | 成员变量 |
| Modifiers | 修饰符 |
| Method | 方法 |
| Declared | 私有的 |