什么是反射
反射是一种机制,可以在程序运行中根据该类的字节码对象动态的创建该类对象。
程序运行时,Java虚拟机会帮每一个类都创建一个字节码对象,(就是我们创建一个对象可以不用 " new 类名()",这种方式创建,使用其他方式创建)
反射的前提
如果我们想通过反射创建一个类的对象,我们就先要获得这对象的字节码对象。
获取字节码对象的三种方式
方式一:通过 "对象名.getClass" 获取该类的字节码(很少使用)
//创建String类的对象 String s = new String(); Class c = s.getClass(); //通过对象的getClass方法获取字节码对象
方式二:通过 “类名.class” 获取该类的字节码对象(很少使用)
//通过 类名.class 获取该类的字节码对象 Class c = String.class;
方式三:通过 “Class.forName("要获取字节码对象类的全包名")” 获取该类的字节码对象(常用)
// Sudent类的全包名 Class c = Class.forName("com.baidu.Student");
Class对象(字节码对象)常用方法介绍
static Class forName(String classPath) 根据参数给的全包名,获取该类的字节码对象 String getName() 获取该字节码对象的全包名 String getSimpleName() 获取这个字节码对象的类名 T newInstance() 创建这个字节码类型的对象
使用反射技术操作构造方法创建类的对象
通过Class对象操作构造需要使用到的方法介绍
Constructor getConstructor(Class....parameterType) 根据对应的参数类型获取对应的构造方法对象,只可以获取public修饰的 Constructor getDeclaredConstructor(Class....parameterType) 根据对应的参数类型获取对应的构造方法对象,可以获取privat修饰的 Constructor[] getConstructors() 获取全部构造方法对象,只能获取public修饰的 Constructor[] getDeclaredConstructors() 获取全部构造方法对象,可以获取private修饰的
Constructor是一个构造方法对象,通过这个类的一些方法我们可以创建对象
T newInstance(Object ....initargs)
根据传入的参数创建对象 void setAccessible(boolean b) 取消私有方法的权限检查,如果调用该方法里面的值一般设置为true(暴力反射) //使用Student类的全包名通过反射获取到 Student的字节码对象 Class c = Class.forName("com.baidu.Student"); //获取Student的有参构造方法的对象 参数为Student类里面对应的参数类型的Class对象类型 // Student(String name, int score) 这个是我Student类里面的一个有参构造方法 //我要获取着构造方法的对象 所以我着方法里面的第一个参数就要是着参数类型的class对象类型 // String name 对应 String.Class int score 对应 int.class 如果要获得无参数构造方法就不要传class对象 Constructor constructor = c.getConstructor(String.class,int.class); //调用newInstancec创建该类对象, 里面的参数顺序为我们上面传入的class对象对应的类型 //c.getConstructor(String.class,int.class) 第一个为String的Clss对象所以我们第一个就要传入String类型的参数 Student student = (Student) constructor.newInstance("小明", 23);
使用反射技术通过创建私有构造方法创建对象
//使用Student类的全包名通过反射获取到 Student的字节码对象 Class c = Class.forName("com.baidu.Student"); // private Student(String name) 这个是我Student类里面的一个私有的有参构造方法 // getDeclaredConstructor获取私有的有参数构造方法 Constructor constructor = c.getDeclaredConstructor(String.class); //设置不进行权限检查 如果不设置就不能通过私有的构造方法创建对象 constructor.setAccessible(true); Student student = (Student) constructor.newInstance("小明");
通过反射操作成员变量
每一个成员变量就是一个Field对象
Class对象获得成员变量对象方法介绍
Field getField(String name) 获取指定名字的成员变量对象,只能获取public修饰的 Field getDeclaredField(String name) 获取指定名字的成员变量对象,可以获取private修饰的 Field[] getFilelds() 获取该字节码对象类型的所有public修饰的成员变量 Field[] getDeclaredField() 获取该字节码对象类型的所有成员变量,包括private修饰的
Field对象常用方法介绍
void set(Object o,Object o1) 设置这个参数对象的值,第一个参数是对象,第二个参数为具体的值 void setAccessible(boolean b) 取消私有方法的权限检查,如果调用该方法里面的值一般设置为true(暴力反射 //使用Student类的全包名通过反射获取到 Student的字节码对象 Class c = Class.forName("com.baidu.Student"); //通过Student字节码对象 调用newInsranee方法 创建该类的对象 Student s = (Student)c.newInstance(); // 通过字节码对象调用getFild方法获取 成员变量对象 参数为你想设置的参数名字 Field field = c.getField("name"); // 第一个参数为 你要问哪一个student对象设置name这个值 //第二个参数为 你要为name设置一个什么值 field.set(s,"老王");
获取私有成员变量的方法和上面获取私有构造方法的差不多,就没有解释了
通过反射技术操作成员方法
每一个方法都是一个Method对象
class对象获取成员方法对象方法介绍
Method getMethod(String methodName,Class...params)d 获取指定的方法对象,第一个参数为要获得的方法对象的方法名,第二个参数为方法要获得的那个方法的参数列表类型的class对象,只可以获取public修饰的 Method getDeclaredMethod(String methodName, Class...params) 和上面的方法一样但是可以获得私有的 Method[] getMethods() 获取这个class对象的类型全部的方法对象,只能获取public修饰的 Method[] getDeclaredMethods() 获取这个class对象的类型全部的方法对象,可以获取private修饰的
Method常用方法介绍
Object invoke(Obejct o,Object....args) 调用方法,第一个为调用该方法的类,也就是获得这个method对象的字节码对象类型的对象 void setAccessible(boolean b) 取消私有方法的权限检查,如果调用该方法里面的值一般设置为true(暴力反射
//使用Student类的全包名通过反射获取到 Student的字节码对象 Class c = Class.forName("com.baidu.Student"); //通过Student字节码对象 调用newInsranee方法 创建该类的对象 Student s = (Student)c.newInstance(); // public void setName(String name) 这个为Student的方法 //获取这个成员方法的对象 第一个参数为方法名,你要获取哪一个方法的Method对象 // 第二个参数为setName的参数类型的class对象 Method m = c.getMethod("setName",String.class); // 第一个参数为 哪一个对象调用着方法 ,第二个参数为传入方法的值 m.invoke(s,"老刘");