动态获取类信息以及动态调用该对象的属性和方法的功能称之为 反射 。
此处的 动态
指的是运行时获取, javac编译 -> 生成.class文件 -> 运行主类
优点:
缺点:
实现反射操作需要4个核心类,这些类都在 java.lang.reflect
包下
1.在Java中获取一个类的class对象,有三种途径:
- // Ⅰ.直接通过类名.class获取class对象
- Class cls1 = Student.class;
-
- // Ⅱ.通过该类的任意实例化对象,调用getClass()方法
- Class cls2 = new Student().getClass();
-
- // Ⅲ.使用Class类提供的静态方法 Class.forName(“包名.类名”);
- Class cls3 = Class.forName("demo.Student");
2.调用 class对象 的 newInstance()
方法产生 Student类 的实例
- // 默认调用该类的无参构造,当访问不到无参构造时,无法使用该方法
- Student stu = (Student) cls.newInstance();
1.通过class 对象获取构造方法
- ① getConstructors() 只能获取当前类的 所有public 权限的构造方法
-
- Constructor[] constructors = cls.getConstructors();
- [public reflect.Student(java.lang.String,int,java.lang.String), public reflect.Student()]
- ② getDeclaredConstructors() 能获取当前类的 所有权限 的构造方法
-
- Constructor[] constructors1 = cls.getDeclaredConstructors();
- [public reflect.Student(java.lang.String,int,java.lang.String), reflect.Student(java.lang.String,int), private reflect.Student(java.lang.String), public reflect.Student()]
③ 拿到 一个无参构造
的constructor对象
Constructor constructor = cls.getDeclaredConstructor();
④ 拿到 一个有参构造
的constructor对象
- Constructor constructor1 = cls.getDeclaredConstructor(String.class);
- Constructor constructor2 = cls.getDeclaredConstructor(String.class, Integer.class);
- Constructor constructor3 = cls.getDeclaredConstructor(String.class, Integer.class, String.class);
2.当拿到特定的Constructor对象时,就可以通过该对象来实例化Student对象
- // 破坏封装,仅限当前JVM进程中的这个constructor1可用
- constructor1.setAccessible(true);
- Student stu = (Student) constructor1.newInstance();
- ① 获取该类的所有方法Method对象,可以拿到当前类以及其父类的 所有public权限 的方法
-
- Method[] methods = cls.getMethods();
- ② 可以拿到当前类的 所有权限 的方法,包括private权限
-
- Method[] methods1 = cls.getDeclaredMethods();
- ③ 拿到当前类的 某个方法 ,getDeclaredMethod(方法名称,方法的参数类型)
-
- Method staticMethod = cls.getDeclaredMethod("staticFunc", String.class);
- ① 可以拿到当前类以及其父类的 所有public的属性
-
- Field[] fields = cls.getFields();
- ② 可以拿到当前类的 所有权限的属性 ,包括private权限
-
- Field[] fields1 = cls.getDeclaredFields();
- ③ 可以拿到 指定属性
-
- Field field = cls.getDeclaredField("name");
- // 第一步,获取 class 对象
- Class cls = new Demo().getClass();
-
- // cls.getDeclaredMethod(方法名称,方法的参数类型)
- Method staticMethod = cls.getDeclaredMethod("staticFunc", String.class);
- // 静态方法的调用不需要实例化对象
- // methodFunc.invoke(具体对象,方法参数);
- staticMethod.invoke(null, "abcde");
-
- Method methodFunc = cls.getDeclaredMethod("fun");
- // fun()方法是private的,需要破坏封装
- methodFunc.setAccessible(true);
- // fun()是成员方法,必须通过Student的对象来调用
- Student stu = (Student) cls.newInstance();
- // 开始调用方法
- // methodFunc.invoke(具体对象,方法参数);
- methodFunc.invoke(stu);
通过反射来调用一个类的方法的过程:
- // 第一步,获取 class 对象
- Class cls = Class.forname("demo.Student");
-
- // 获取指定的属性
- Field field = cls.getDeclaredField("name");
- field.setAccessible(true); // 因为name是private修饰的属性
-
- // name是成员属性,所以需要Student的实例化对象
- Student stu = (Student) cls.newInstance();
-
- // 设置属性值:set(具体对象, 属性值);
- field.set(stu, "张三");
- // 获取属性值:通过具体的Student对象获取name属性
- System.out.println(field.get(stu));
通过反射来获取一个类的属性的过程:
总结:
提示:这里对文章进行总结:
以上就是今天的学习内容,本文是Java反射的学习,认识什么是反射,反射相关的类,以及反射的原理和过程。之后的学习内容将持续更新!!!