• Java中的反射


    目录

    一、认识反射

    1、反射的概念

    2、反射的作用

    3、反射相关的类

    二、反射的使用

    1、Class类

    2、调用类中的私有构造方法

    3、使用类中的私有成员变量

    4、调用类中的私有成员方法 

    三、反射的优点和缺点

    1、优点

    2、缺点


    一、认识反射

    1、反射的概念

            Java的反射机制是在运行状态中,对于任意一个类,都能够获得这个类的所有属性和方法;对于任意一个对象,都能够调用它的任何方法和属性。这种动态获取类的信息以及动态调用方法的功能称为Java语言的反射(reflection)机制。

    2、反射的作用

            Java程序中一些对象在运行时会出现两种类型:运行时类型编译时类型,例如一个向上转型的代码:Bird bird = new Animal();其中,bird在编译时类型为Bird,运行时类型为Animal,通过反射机制就能在程序运行时发现该对象和类的真实信息。

    3、反射相关的类

    Class类代表类的实体,在运行的Java应用程序中表示类和接口
    Field类代表类的成员变量/字段
    Method类代表类的方法
    Constructor类代表类的构造方法

    二、反射的使用

    1、Class类

            在反射之前,我们需要先拿到当前需要反射的类的Class对象,然后通过Class对象调用相关的方法,来达到反射的目的。

    获得Class对象的三种方式:

    (1)使用Class.forName方法("类的全路径名");

    (2)使用需要反射的类名调用class方法;

    (3)使用需要反射的类的对象调用getClass方法

    但是通过三种方式获取的Class对象都是相同的,也就是说,一个类只有一个对应的Class对象

    Class类中常用获得类相关的方法
    方法作用
    getClassLoader()获得类的加载器
    getDeclaredClasses()返回一个数组,数组中包含该类中所有类和接口类的对象
    forName(String classRoad)根据类的路径返回类的Class对象(该方法是静态成员方法)
    newInstacne()创建类的实例
    getName()获得类的完整路径名

    2、调用类中的私有构造方法

    获得类中构造器相关的方法(返回值为Constructor类型相关)

    方法作用
    getConstructor(Class...parameterTypes)获得该类中与参数类型匹配的公有的构造方法
    getConstructors()获得该类中所有公有的构造方法
    getDeclaredConstructor(Class...parameterTypes)获得该类中与参数类型匹配的构造方法
    getDeclaredConstructors()获得该类中所有构造方法

    示例: 

    创建一个Student类:

    1. public class Student {
    2. public String name;//公共的成员变量
    3. private int id = 1;//私有的成员变量
    4. public Student(){
    5. System.out.println("公共的构造方法");
    6. }
    7. private Student(int id){
    8. this.id = id;
    9. System.out.println("私有的构造方法");
    10. }
    11. public void func(){
    12. System.out.println("公共的成员方法");
    13. }
    14. private void func2(String s){
    15. System.out.println(s);
    16. }
    17. @Override
    18. public String toString() {
    19. return "Student{" +
    20. "name='" + name + '\'' +
    21. ", id=" + id +
    22. '}';
    23. }
    24. }

    在同一个包中的Test类中通过Student类私有的构造方法创建一个Student对象:

    1. public class Test {
    2. public static void reflectPrivateConstructor(){
    3. try {
    4. //获得Class对象
    5. Class c1 = Class.forName("reflect.Student");
    6. //调用getDeclaredField(String name)方法
    7. Constructor constructor = c1.getDeclaredConstructor(int.class);
    8. //调用setAccessible(boolean)后可修改访问权限
    9. constructor.setAccessible(true);
    10. //通过Constructor对象创建Student对象
    11. Student student = (Student) constructor.newInstance(100);
    12. //输出创建好的Student对象
    13. System.out.println(student);
    14. } catch (NoSuchMethodException e) {
    15. e.printStackTrace();
    16. } catch (InvocationTargetException e) {
    17. e.printStackTrace();
    18. } catch (InstantiationException e) {
    19. e.printStackTrace();
    20. } catch (IllegalAccessException e) {
    21. e.printStackTrace();
    22. } catch (ClassNotFoundException e) {
    23. e.printStackTrace();
    24. }
    25. }
    26. public static void main(String[] args) throws ClassNotFoundException {
    27. reflectPrivateConstructor();
    28. }
    29. }

    代码运行结果:

     

    3、使用类中的私有成员变量

    获得类中字段相关的方法(返回值为Field类型相关)

    方法作用
    getField(String name)获得该类中某个公有的字段
    getFields()获得该类中所有公有的字段
    getDeclaredField(String name)获得该类中某个字段
    getDeclaredFields()获得该类中所有字段

    示例: 

    反射Student类中的私有成员变量

    1. public class Test {
    2. public static void reflectPrivateField(){
    3. try {
    4. //获得Class对象
    5. Class c1 = Class.forName("reflect.Student");
    6. //getDeclaredField(String name)方法
    7. Field field = c1.getDeclaredField("id");
    8. //调用setAccessible(boolean)后可修改访问权限
    9. field.setAccessible(true);
    10. //通过Class类反射一个Student对象
    11. Student student = (Student) c1.newInstance();
    12. //修改指定Student对象的静态成员变量:id = 500
    13. field.set(student,500);
    14. //输出Student对象
    15. System.out.println(student);
    16. } catch (ClassNotFoundException e) {
    17. e.printStackTrace();
    18. } catch (NoSuchFieldException e) {
    19. e.printStackTrace();
    20. } catch (InstantiationException e) {
    21. e.printStackTrace();
    22. } catch (IllegalAccessException e) {
    23. e.printStackTrace();
    24. }
    25. }
    26. public static void main(String[] args) {
    27. reflectPrivateField();
    28. }
    29. }

    代码运行结果:

    4、调用类中的私有成员方法 

    获得类中方法相关的方法(返回值为Method类型相关)

    方法作用
    getMethod(String name,Class...parameterTypes)获得该类中某个公有的方法
    getMethods()获得该类中所有公有的方法
    getDeclaredMethod(String name,Class...parameterTypes)获得该类中某个方法
    getDeclaredMethods()获得该类中所有方法

     示例: 

    反射Student类中的私有成员方法

    1. public class Test {
    2. public static void reflectPrivateMethod(){
    3. try {
    4. //获得Class对象
    5. Class c1 = Class.forName("reflect.Student");
    6. //调用getDeclaredMethod(String name,Class...parameterTypes)方法
    7. Method method = c1.getDeclaredMethod("func2",String.class);
    8. //获取私有的属性或方法一般都要调用setAccessible(boolean)方法
    9. method.setAccessible(true);
    10. //通过Class类反射一个Student对象
    11. Student student = (Student) c1.newInstance();
    12. //Method对象调用invoke方法
    13. //让指定的Student对象调用指定的私有方法并传参
    14. method.invoke(student,"通过反射机制调用Student类的私有方法");
    15. } catch (ClassNotFoundException e) {
    16. e.printStackTrace();
    17. } catch (NoSuchMethodException e) {
    18. e.printStackTrace();
    19. } catch (InstantiationException e) {
    20. e.printStackTrace();
    21. } catch (IllegalAccessException e) {
    22. e.printStackTrace();
    23. } catch (InvocationTargetException e) {
    24. e.printStackTrace();
    25. }
    26. }
    27. public static void main(String[] args) {
    28. reflectPrivateMethod();
    29. }
    30. }

    代码运行结果:

    三、反射的优点和缺点

    1、优点

    (1)对于任意一个类,都能够获得这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;

    (2)增加程序的灵活性和扩展性,降低耦合性。

    2、缺点

    (1)使用反射会导致程序效率降低(为了获得一个类的对象,调用了Class类中的多个方法);

    (2)反射机制绕过了源代码,可能会带来维护问题。

  • 相关阅读:
    ChatGPT生成量化交易策略,真好玩
    6-redis配置文件(redis.conf)详解
    能直接运营的发接任务平台小程序搭建开发演示
    【OFDM】多径信道下OFDM通信系统误码率仿真附matlab代码
    你可能需要的vue相关考点汇总
    向量机SVM代码实现
    【C++】模版进阶
    Leetcode 850. 矩形面积 II
    只有微信账号,我可以查询聊天记录吗?
    PHP-composer安装扩展安装,批量操作合并pdf
  • 原文地址:https://blog.csdn.net/m0_67683346/article/details/126670993