反射的用法及其介绍
反射的好处
有两个方向
第一个方向:无视修饰符访问类中的内容。但是这种操作在开发中一般不用,都是框架层来用的。
第二个方向:反射可以跟配置文件结合起来使用,动态的创建对象,动态的调用方法。
获取字节码文件对象的三种方式
-
Class这个类里面的静态方法forName(“全类名”)(最常用)
Class clazz1=Class.forName("类的全类名");
-
通过class属性获取
//类名.class Class clazz2 = Student.class;
-
通过对象获取字节码文件对象
Student s = new Student(); Class clazz3 = s.getClass();
获取构造方法
规则:
get表示获取,Declared表示私有,最后的s表示所有,复数形式.
如果当前获取到的是私有的,必须要临时修改访问权限,否则无法使用
方法名 | 说明 |
---|---|
Constructor<?>[] getConstructors() | 获得所有的构造(只能public修饰) |
Constructor<?>[] getDeclaredConstructors() | 获得所有的构造(包含private修饰) |
Constructor getConstructor(Class<?>… parameterTypes) | 获取指定构造(只能public修饰) |
Constructor getDeclaredConstructor(Class<?>… parameterTypes) | 获取指定构造(包含private修饰) |
获得所有构造用Constructor[]接受,for循环遍历
获取指定构造参数格式要以下形式:
Constructor con = clazz.getDeclaredConstructor(String.class, int.class);
获取的构造方法就是这类:
获取构造方法的权限修饰符和每个参数
//获取构造方法的权限修饰符
int modifiers = con.getModifiers();
//获取构造方法的每个参数
Parameter[] parameters = con.getParameters();
实例化对象
涉及到的方法:newInstance
如果将私有构造方法创建对象,需要临时修改构造方法的访问权限(暴力反射)
//1.获取整体的字节码文件对象
Class clazz = Class.forName("全类名");
//2.获取有参构造方法
Constructor con1 = clazz.getDeclaredConstructor(String.class);
Constructor con2 = clazz.getDeclaredConstructor(String.class, int.class);
//3.利用构造方法创建对象
student stu =(student) con1.newInstance("funnyboy");
System.out.println(stu);
//3.将私有构造方法创建对象
//临时取消权限校验
con2.setAccessible(true);
student stu2 = (student) con2.newInstance("kai桑", 20);
System.out.println(stu2);
获取成员变量
方法名 | 说明 |
---|---|
Field[] getFields() | 返回所有成员变量对象的数组(只能拿public的) |
Field[] getDeclaredFields() | 返回所有成员变量对象的数组,存在就能拿到 |
Field getField(String name) | 返回单个成员变量对象(只能拿public的) |
Field getDeclaredField(String name) | 返回单个成员变量对象,存在就能拿到 |
1.获取class对象
2.获取成员变量的对象(Field对象)
Field[] fields2 = clazz.getDeclaredFields("name");
获取成员变量并获取值和修改值
方法 | 说明 |
---|---|
void set(Object obj, Object value) | 赋值 |
Object get(Object obj) | 获取值 |
//1.获取class对象
Class clazz = Class.forName("reflect.student");
//2.获取指定的成员变量
Field name=clazz.getDeclaredField("name");
System.out.println(name);
//3.获取成员变量记录的值
student s = new student("zhangsan", 23);
//产生Student对象
Object obj =clazz.getDeclaredConstructor().newInstance();
//临时取消权限校验
name.setAccessible(true);
//Field成员变量的get返回的是object需要强转
String value =(String)name.get(s);
System.out.println(value);
//修改对象里面记录的值
name.set(s,"lisi");
name.set(obj,"zxk");
System.out.println(s);
System.out.println(obj);、
//private java.lang.String reflect.student.name
//zhangsan
//student{name='lisi', age=23}
//student{name='zxk', age=0}
获取成员变量的权限修饰符,名字,数据类型
//1.获取class对象
Class clazz = Class.forName("reflect.student");
//2.获取单个的成员变量
Field name=clazz.getDeclaredField("name");
System.out.println(name);
//获取权限修饰符
int modifiers = name.getModifiers();
System.out.println(modifiers);
//获取成员变量的名字
String n = name.getName();
System.out.println(n);
//获取成员变量的数据类型
Class<?> type = name.getType();
System.out.println(type);
获取成员方法
方法名 | 说明 |
---|---|
Method[] getMethods() | 返回所有成员方法对象的数组(只能拿public的) |
Method[] getDeclaredMethods() | 返回所有成员方法对象的数组,存在就能拿到 |
Method getMethod(String name, Class<?>… parameterTypes) | 返回单个成员方法对象(只能拿public的) |
Method getDeclaredMethod(String name, Class<?>… parameterTypes) | 返回单个成员方法对象,存在就能拿到 |
1.获取class对象
2.获取获取方法(包含私有)
Method[] methods2 = clazz.getDeclaredMethods();
2.或者获取指定方法
Method method4 = clazz.getMethod("eat",String.class); //写参数防止方法的重载
获取成员方法并运行
Object invoke(Object obj, Object… args) :运行方法
参数一:用obj对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)
//1.获取字节码文件对象
Class clazz = Class.forName("com.itheima.a02reflectdemo1.Student");
//2.获取一个对象
//需要用这个对象去调用方法
//获取一个对象
Object obj = clazz.getDeclaredConstructor().newInstance();
//3.获取一个指定的方法
//参数一:方法名
//参数二:参数列表,如果没有可以不写
Method eatMethod = clazz.getMethod("eat",String.class);
//运行
//参数一:表示方法的调用对象
//参数二:方法在运行时需要的实际参数
//注意点:如果方法有返回值,那么需要接收invoke的结果
//如果方法没有返回值,则不需要接收
String result = (String) eatMethod.invoke(obj, "重庆小面");
//运行此方法后,并返回值
System.out.println(result);
//参数二:方法在运行时需要的实际参数
//注意点:如果方法有返回值,那么需要接收invoke的结果
//如果方法没有返回值,则不需要接收
String result = (String) eatMethod.invoke(obj, "重庆小面");
//运行此方法后,并返回值
System.out.println(result);