反射:拥有获取类信息的能力
创建对象的流程:
1、自定义java文件—>demo.java—>javac命令编译成demo.class——>通过.java命令运行到JVM内存(加载到方法区,方法区存储的是类信息 (类对象) )
(简单理解为:从类到对象的过程)
2、main方法入栈——>main方法创建类student对象——>student对象在堆内存中开辟内存空间——>堆当中,对象内部有变量的空间,存有变量(name,age,password,sno,age)
如何获取类对象?
方式一:通过Class.forName(“全类名”)变量来获取类对象(全类名:包名+类名)------(对应磁盘阶段,磁盘阶段就是地址形式进行存储)
方式二:类名.class ------ 类本身已经构建成了类对象,加载到磁盘当中了,因此不需要写全类名,直接类名.class就能获取类对象(对应类对象阶段)
方式三: 对象名.getClass ------ 已经生成了对象,(回退)(对应运行阶段)
想获取成员变量——>通过Field类/类对象提供了一些方法
—1—>类对象.getDeclaredFields(); -------获取所有的变量,由Field[]数组进行接收
Field[] fields = class1.getDeclaredFields();
—2—>类对象.getFields(); -------获取全部的public修饰的变量,由Field[]数组进行接收
Field[] fields1 = class1.getFields();
—3—>类对象.getDeclaredField(“参数”); -------获取指定的变量,参数为指定变量名,由Field变量进行接收
Field name = class1.getDeclaredField(“name”);
—4—>类对象.getField(“参数”); -------获取指定的public修饰的变量,参数为指定变量名,由Field变量进行接收
Field password= class1.getField(“password”);
总结:方法上有Declared能获取全部的,没有Declared只能获取public修饰的变量
当sno是protected类型的时候
Field sno = class1.getField(“sno”);//会报错
—1—>类对象.getDeclaredMethods() ---------获取全部的方法,由Method[]数组接收
Method[] methods = class1.getDeclaredMethods();
—2—>类对象.getMethods() ---------获取全部的public修饰的方法,由Method[]数组接收
Method[] methods = class1.getMethods();
—3—>类对象.getDeclaredtMethod(“方法名”,“该参数的反射类型 . 该方法的参数”) ---------获取指定的方法,所有类型都可以获取,由Method变量进行接收
( 方法没有参数的时候就不写后面的"参数的类型 . 该方法的参数" )
—4—>类对象.getMethod(“方法名”,“该参数的反射类型 . 该方法的参数”) ---------获取指定的public类型修饰的方法,由Method变量进行接收
—1—>类对象.getDeclaredConstructors() ---------获取全部的构造方法,由Constructor[]数组接收
Constructor[] Constructor = class1.getDeclaredConstructors();
—2—>类对象.getConstructors() ---------获取全部的public修饰的构造方法,由Constructor[]数组接收
Constructor[] Constructor = class1.getConstructors();
—3—>类对象.getDeclaredConstructor(该参数的反射类型) ---------获取指定的构造方法,由Constructor变量接收
Constructor Constructor = class1.getDeclaredConstructor();
—4—>类对象.getConstructor(该参数的反射类型) ---------获取指定的public类型的构造方法,由Constructor变量接收
Constructor Constructor = class1.getConstructor();
所有构造器的方法名是一样的
通过调用newInstance()方法来创建对象(constructor.newInstance();)
Student student = (Student) constructor.newInstance();//利用构造器生成对象
如果想要使用私有类型的数据,必须使用暴力反射
——》constructor.setAccessible(true);
对于私有的数据,必须使用暴力反射才能使用,不是私有类型的数据,不需要使用暴力反射
Class> clazz = Class.forName("fanshe.com.Student");
Constructor constructor = clazz.getDeclaredConstructor();
//如果想要使用私有类型的数据,必须使用暴力反射
constructor.setAccessible(true);
Student student = (Student) constructor.newInstance();//利用构造器生成对象
System.out.println(student.sex);//这样才能使用
注:(总结)
构造器本质:创建对象
1、获取指定的构造器:如果是public修饰的,用getConstructor(“参数的反射类型”),如果是非public修饰的用getDeclaredConstructor(“该参数的反射类型”)
2、通过调用newInstance()方法来创建对象------newInstance(参数的值):如果是private类型修饰的构造器,需要暴力反射。
【获取到的指定构造器名.setAccessible(true);】
3、想使用public 和 protected 等非私有类型修饰的数据 ------ :不需要使用暴力反射
调用invoke(对象,该方法的参数)方法 用来执行指定的方法
Class> clazz = Class.forName("fanshe.com.Student");
Method method = clazz.getMethod("eat",String.class);//为什么要创建对象??——》获取类信息是处在类对象阶段,方法、变量在第三阶段
//因为获取的类信息来源于第二阶段(对象阶段),但是要使用方法需要进入到第三阶段,创建对象,给方法内存空间才能进行调用
Student student = new Student("张三");
method.invoke(student,"水果");
———————————————以上是不使用反射的时候,使用反射是下面这样———————————————————————
Class> clazz = Class.forName("fanshe.com.Student");
Constructor construcor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
Student student = (Student) constructor.newInstance();//调用newInstance()来创建当前对象
method.invoke(student,"水果");--------
Student.java当中有:
private Student(){}
注:
1、获取指定所有的方法
2、创建对象 -------为什么要创建对象??——》因为获取的类信息来源于第二阶段(对象阶段),但是要使用方法需要进入到第三阶段,创建对象,给方法内存空间才能进行调用,所以需要提前创建出对象
3、如果是private类型修饰,需要暴力反射 ,如果是其他类型不需要暴力反射
4、调用invoke方法---------获取的方法类信息.invoke(对象,参数的值…);
Class> clazz = Class.forName("fanshe.com.Student");
//获取类信息
Field field = clazz.getDeclaredField();
field.setAccessible(true);
//赋值 set方法
field.set(student,"张三");
//取值 get方法
field.get(student);
System.out.println(field.get(student));//输出:张三
注:(总结)
1、获取指定的变量------如果是public修饰的变量getField(“方法名”) 、如果是非public修饰的用 类对象.getDeclareField(“name”)
2、创建对象 ------为什么要创建对象??—>因为获取的类信息来源于第二阶段(对象阶段),但是要使用变量需要进入第三阶段,创建对象,给变量内存空间才能进行调用
3、如果是privated修饰的变量需要暴力反射 获取的变量类信息.setAccessible(true)
4、赋值:变量信息.set(对象,值)
5、取值:变量信息.get(对象)