反射
官方解释:Reflection允许以编程的方式访问有关已加载类的字段、方法和构造函数的信息,以及使用反射字段、方法和构造函数在封装和安全限制内对其底层对应项进行操作(其实指的是加载类的字节码到内存,并以编程的方法解刨出类中的各个成分(成员变量、方法、构造器等)
因为反射获取的是类的信息,那么反射的第一步首先获取到类才行。由于Java的设计原则是万物皆对象,获取到的类其实也是以对象的形式体现的,叫字节码对象,用Class类来表示。获取到字节码对象之后,再通过字节码对象就可以获取到类的组成成分了,这些组成成分其实也是对象,其中每一个成员变量用Field类的对象来表示、每一个成员方法用Method类的对象来表示,每一个构造器用Constructor类的对象来表示。
1.1获取类的字节码对象
-
获取字节码对象的三种方式
//1.通过类 Class c1 = Student.class; //2.通过全类名 Class c2 = Class.forName("com.itheima.d2_reflect.Student"); System.out.println(c1 == c2); //true //3.通过对象 Student s = new Student(); Class c3 = s.getClass();
1.2 获取类的构造器&使用
- Class类中获取构造器的方法
-
代码演示
//1、反射第一步:必须先得到这个类的Class对象 Class c = Cat.class; //2、获取类的全部构造器 Constructor[] constructors = c.getDeclaredConstructors(); //遍历数组中的每一个构造器对象。 for(Constructor constructor: constructors){ System.out.println(constructor.getName()+"---> 参数个 数:"+constructor.getParameterCount()); } //3、获取类public修饰的空参数构造器 Constructor constructor1 = c.getConstructor(); System.out.println(constructor1.getName()+"---> 参数个 数:"+constructor1.getParameterCount()); //4、获取private修饰的有两个参数的构造器,第一个参数String类型,第二个参数int类型 Constructor constructor2 = c.getDeclaredConstructor(String.class,int.class);
-
使用:通过构造器Constructor的方法初始化对象并返回
- T newInstance(Object … initargs) //调用构造器,传入参数完成对象初始化并返回
- void setAccessible(boolean flag) //设置为true,表示暴力反射
代码示例:
constructor2.setAccessible(true) Cat c = (Cat)constructor2.newInstance("加菲猫",2)
1.3反射获取成员变量&使用
- Class类获取成员变量的方法
-
代码示例:
//1.反射第一步,获取类的Class对象 Class c = Cat.class //2.获取类的全部成员变量数组 Field[] fields = c.getDeclaredFields(); //3.获取某个成员变量 Field fName = c.getDeclaredField("name") System.out.println(fName.getName() + "----" + fName.getType())
-
使用
- void set(Object obj,Object value) //赋值
- Object get(Object obj) //取值
- void setAccessible(boolean flag)//设置为true,表示暴力反射
代码示例:
fName.setAccessible(true) fName.set(cat,"加菲猫") //赋值 String name = (String) fName.get(cat) //取值
1.4 反射获取成员方法
-
Class类获取成员方法的方法
-
代码示例
-
使用
- Object invoke(Object obj,Object … args)//执行方法
- void setAccessible(boolean flag) //设置为true,表示暴力反射
代码示例:
//1、反射第一步:先获取到Class对象 Class c = Cat.class; //2、获取类中的全部成员方法 Method[] methods = c.getDecalaredMethods(); //3、获取private修饰的run方法,得到Method对象 Method run = c.getDecalaredMethod("run"); //执行run方法,在执行前需要取消权限检查 Cat cat = new Cat(); run.setAccessible(true); Object rs1 = run.invoke(cat); System.out.println(rs1) //5、获取private 修饰的eat(String name)方法,得到Method对象 Method eat = c.getDeclaredMethod("eat",String.class); eat.setAccessible(true); Object rs2 = eat.invoke(cat,"鱼儿"); System.out.println(rs2)