Java反射机制: 在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性), 这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制。通俗点讲,通过反射,该类对我们来说是完全透明的,想要获取任何东西都可以。
首先第一步,加载类,在类无法被实例化的情况下有三种方式加载类。
//加载类,把加载好的类放进Class<?>中,?代表一切,ReflectDemo1是当前类的类名,Person是要加载的类的类名,要加载的类名要连包名也写上。
//第一种方式不会执行Person类的静态初始化块
第一种: Class<?> class1 = ReflectDemo1.class.getClassLoader()
.loadClass("com.wen.reflect.Person");
//第二种方式会执行Person类的静态初始化块
第二种: Class<?> class2 = Class.forName("com.wen.reflect.Person");
//第三种方式不会执行Person类的静态初始化块
第三种: Class<?> class3 = Person.class;
通过反射机制调用构造器实例化一个类的对象:
// getDeclaredConstructor():返回一个Constructor对象,该对象反映此Class对象所表示的类或接口的指定构造方法, 此方法连无法直接访问的构造器也能拿到。
Constructor<?> constructor1 = class2.getDeclaredConstructor(String.class,int.class);//拿到构造器,参数是构造器的形参列表的参数类型,通过形参列表来确定一个构造器。
constructor1.setAccessible(true);//必须设置开放权限,打破封装,允许访问
Person person = (Person) constructor1.newInstance("小明", 20);//用拿到的Constructor对象来new一个实例,也就是创建对象,返回的是object类型的,需强制转换,后面是两个实参
System.out.println("姓名: " + person.getName());
System.out.println("年龄: " + person.getAge());
输出结果如下图:
通过反射机制调用无法直接访问的方法:
//getDeclaredMethod():返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法,无法直接访问的方法也可以拿到,第一个参数是要调用的方法名,后面的参数都是要调用的方法的形参列表的参数类型,有多少要写多少,要与要调用的方法的形参列表一一对应。
Method method2=class2.getDeclaredMethod("test", String.class);
method2.setAccessible(true); //必须设置开放权限,打破封装,允许访问。
//invoke():默认返回的是object类型,可以用强制转换转换成String类型,第一个参数是一个对象,后面的参数都是要调用的方法的实参
String str2= (String) method2.invoke(person, "无法直接访问");
System.out.println(str2);
输出结果如下图:
通过反射机制获取或者设置无法直接访问的成员变量:
//getDeclaredField():返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段,无法直接访问的字段也可以拿到。
//设置值
Field field=class2.getDeclaredField("name");//通过变量名来匹配变量 field.setAccessible(true); //必须设置开放权限,打破封装,允许访问。
field.set(person, "小小明");//给person这个对象设置变量name的值
System.out.println("设置值:" + person.say("111111"));
//获取值
System.out.println("获取值:" + field.get(person));
输出结果如下图: