目录
概念:
首先,我们要认识下反射是用来干什么的,目前而言,我所认知,反射即是通过获取类对象,来间接获取类中的属性、构造方法、普通方法,来对其间接操作
这里需注意类对象与类的对象的区别:
类对象是唯一的;
类的对象是可以有多个的,也就是实例化对象
获取类对象(三种方式)
@Test
public void test_01() throws ClassNotFoundException {
// 方式一:通过类的对象获取类对象
// 实例化一个学生对象
Student stu = new Student();
Class aClass = stu.getClass();
// 方式二:通过类.class获取
Class bClass = Student.class;
// 方式三:通过Class.forName(全限定包名) 注意:全限定包名要定位到类名上,也就是引用的类的包名全称
Class cClass = Class.forName("com.school.data02.study04.Student");
}
那么,类对象获取到了,又能做什么呢?接下来就是用类对象来实施对类中的属性、构造方法、普通方法进行获取操作,我们一般称之为“反射”
反射三部曲:
获取类中的属性: Field
@Test
public void test_03() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
// 1、获取类对象 一般使用方式三来获取哈,较为实用
Class cls = Class.forName("com.school.data02.study04.Student");
// 2、先来获取指定的公开的属性 这里返回值用Field类来接收
Field field = cls.getField("name");
// 注意:这里对属性进行赋值前,我们需要提供一个对象,为其对象的该属性赋值,不然,你还想给属性赋默认值啊!
// 实例化一个类的对象 这里默认Object接收哈,别酱
Object obj = cls.newInstance();
// 3、对属性进行赋值 注意: 我这里name属性为String型,什么型赋什么值
field.set(obj,"木子");
// 4、获取属性中的值
// 这里可能容易混哈, 要记住field是属性名, 以此来获取这个对象的属性值
Object name = field.get(obj); // 返回值还是用Object接收
System.out.println(name);
// 5、获取所有公开的属性(包括父类的)
Field[] fields = cls.getFields();
// 数组流输出查看,不懂就用for遍历查看
Arrays.stream(fields).forEach(System.out::println);
// 6、获取指定的私有属性,使用方式都差不多
Field f = cls.getDeclaredField("age");
// System.out.println(f.getName());
// 私有属性进行赋值时,需要进行暴力反射,不然会报错
f.setAccessible(true); // 即:暴力反射,也就是打开某个开关而已,不用太理解
f.set(obj,12); // 赋值
System.out.println(obj);
// 7、获取所有的属性(包括私有的)
Field[] f_s = cls.getDeclaredFields();
Arrays.stream(f_s).forEach(System.out::println);
}
获取构造方法 Constructor
@Test
public void test_04() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//1、获取类对象
Class cls = Class.forName("com.school.data02.study04.Student");
//获取这个类的指定的构造方法 有参则需要带上参数 类型.class形式
Constructor constructor = cls.getConstructor(String.class,String.class,int.class);
System.out.println(constructor);
//通过构造方法new对象 必须对应上方构造的参数的类型及个数
Object obj = constructor.newInstance("001","jack",23);
System.out.println(obj);
System.out.println("-------------");
//获取所有公开的构造方法
Constructor[] constructors = cls.getConstructors();
Arrays.stream(constructors).forEach(System.out::println); // 遍历输出
System.out.println("--------------");
//获取所有的构造方法(包括私有的)
Constructor[] constructors_s = cls.getDeclaredConstructors();
Arrays.stream(constructors_s).forEach(System.out::println);
System.out.println("---------------");
//获取指定私有的有参构造方法
Constructor constructor_s = cls.getDeclaredConstructor(String.class,int.class);
System.out.println(constructor_s);
//设置私有可以访问(暴力反射)
constructor_s.setAccessible(true); // 私有需要暴力反射
Object obj_s = constructor_s.newInstance("彩虹",23);
System.out.println(obj_s);
}
获取普通方法 Method
@Test
public void test_05() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
//获取类对象
Class cls = Class.forName("com.school.data02.study04.Student");
Object obj = cls.newInstance();
//获取指定公开的方法
Method method = cls.getMethod("method", String.class);
System.out.println(method.getName());
//利用反射调用方法,并接收返回值 方法的调用 .invoke()的新使用 有参则传参
Object result = method.invoke(obj,"jack");
System.out.println(result);
System.out.println("----------------------");
//获取所有的公开的方法(包括父类的公开的方法)
Method[] methods = cls.getMethods();
Arrays.stream(methods).forEach(System.out::println);
System.out.println("-----------------------");
//获取指定的私有方法
Method method_s = cls.getDeclaredMethod("s_method", String.class);
System.out.println(method_s);
//利用反射调用私有方法,并接收返回值(如果方法没有返回值。那么invoke方法就返回null)
method_s.setAccessible(true); // 暴力反射
Object s_result = method_s.invoke(obj,"Mark");
System.out.println(s_result);
System.out.println("------------------");
//获取本类中所有的方法(包括私有的)
Method[] methods_s = cls.getDeclaredMethods();
Arrays.stream(methods_s).forEach(System.out::println);
}
总结:
以上即为反射的基本内容,这里只是简单认识下反射的使用方式,谢谢您的耐心阅读