Java反射基础篇:你真的了解Java反射吗?
发布日期:2025-04-02 02:20:08 浏览次数:12 分类:精选文章

本文共 3712 字,大约阅读时间需要 12 分钟。

反射的思想及作用

反射是一种强大的技术,它能够让程序在运行时对类的信息进行动态获取和操作。在编写程序时,我们常常需要面对数据结构的频繁更改的情况,比如从HashMap切换到LinkedHashMap。每次发生这种更改都需要重新修改源码,编译并重启程序,这种效率非常低。然而,通过使用反射,我们可以在不修改源码的情况下灵活地使用不同的数据结构。

在学习反射之前,先了解正射的概念。new关键字实例化对象的方式就是正射的典型体现。下面是一个实例化HashMap的示例:

Map
map = new HashMap<>();
map.put(1, 1);

如果需要切换到LinkedHashMap,代码就需要改为:

Map
map = new LinkedHashMap<>();
map.put(1, 1);

这种需求变更需要频繁修改源码,显然不够高效。通过引入开关机制,我们可以在程序运行时动态决定使用哪一种数据结构:

public Map
getMap(String param) {
map = null;
if (param.equals("HashMap")) {
map = new HashMap<>();
} else if (param.equals("LinkedHashMap")) {
map = new LinkedHashMap<>();
} else if (param.equals("WeakHashMap")) {
map = new WeakHashMap<>();
}
return map;
}

传入不同的参数可以灵活选择数据结构,但如果需要支持更多类的使用,反射就派上用场了。通过反射,我们可以在运行时动态获取类信息并创建实例:

public Map
getMap(String className) {
Class
clazz = Class.forName(className);
Constructor
constructor = clazz.getConstructor();
return (Map
) constructor.newInstance();
}

无论是HashMap还是TreeMap,只要它们实现了Map接口,都可以通过全类名传入方法中使用,无需修改源码。

反射的基本使用

反射的主要组成部分包括ClassFieldConstructorMethod四个类。它们分别用于获取类信息、属性、构造器和方法。

获取Class对象

获取Class对象的方法有三种:

  • 使用类名直接获取类对象:
  • Class
    clazz = SmallPineapple.class;
    1. 通过实例获取对应的类对象:
    2. SmallPineapple instance = new SmallPineapple();
      Class
      clazz = instance.getClass();
      1. 使用全限定名获取类对象:
      2. Class
        clazz = Class.forName("com.example.SmallPineapple");

        构造类实例

        通过反射,可以选择两种方式构造类的实例:

      3. 使用newInstance()方法:
      4. Class
        clazz = Class.forName("com.example.SmallPineapple");
        Object instance = clazz.newInstance();
        1. 使用构造器和newInstance()方法:
        2. Class
          clazz = Class.forName("com.example.SmallPineapple");
          Constructor
          constructor = clazz.getConstructor(String.class, Integer.class);
          constructor.setAccessible(true);
          Object instance = constructor.newInstance("小菠萝", 21);

          获取类信息

          通过反射,可以获取类中定义的所有信息,包括变量、方法和构造器。

          获取变量(Field)

        3. 获取类中所有公共变量:
        4. Class
          clazz = SmallPineapple.class;
          Field
          [] fields = clazz.getFields();
          1. 根据变量名获取特定变量:
          2. Field
            weightField = clazz.getDeclaredField("weight");

            获取方法(Method)

          3. 获取类中所有公共方法:
          4. Class
            clazz = SmallPineapple.class;
            Method
            [] methods = clazz.getMethods();
            1. 根据方法名和参数类型获取特定方法:
            2. Method
              getInfoMethod = clazz.getMethod("getInfo");

              获取构造器(Constructor)

            3. 获取类中所有构造器:
            4. Class
              clazz = SmallPineapple.class;
              Constructor
              [] constructors = clazz.getConstructors();
              1. 根据参数类型获取特定构造器:
              2. Constructor
                defaultConstructor = clazz.getConstructor();

                获取注解

                反射还支持获取注解信息,注解信息可以定义在变量、方法和构造器上。

              3. 获取类上的所有注解:
              4. Annotation
                [] annotations = clazz.getAnnotations();
                1. 获取特定注解:
                2. Annotation
                  retentionAnnotation = clazz.getAnnotation(Retention.class);

                  调用方法

                  可以通过反射调用方法,方法的invoke()方法可以传递参数:

                  Class
                  clazz = Class.forName("com.example.SmallPineapple");
                  Method
                  getInfoMethod = clazz.getMethod("getInfo");
                  Object instance = (SmallPineapple) clazz.newInstance();
                  Object result = getInfoMethod.invoke(instance);

                  反射的应用场景

                3. Spring IOC容器:Spring通过读取配置文件解析出所有<bean>标签,并使用反射实例化对象,存储在IOC容器中。

                4. 反射+工厂模式:通过反射和工厂模式结合,通过传入不同的类名实例化新的子类,无需修改工厂类代码。

                5. JDBC连接数据库:通过反射加载数据库驱动类,灵活配置数据源。

                6. JDBC 加载驱动类

                  在程序中,JVM不会自动加载外部库类,所以我们需要通过Class.forName()动态加载驱动类:

                  public class DBConnectionUtil {
                  private static final String DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver";
                  public static Connection getConnection() {
                  Class.forName(DRIVER_CLASS_NAME);
                  return DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8", "root", "root");
                  }
                  }

                  通过修改配置文件中的驱动类名,程序可以灵活切换数据库驱动。

                  反射的优缺点

                  • 优势

                    • 增加程序灵活性,能够在运行时动态选择类实例化。
                    • 适用于频繁改变需求的场景,避免修改源码。
                  • 缺点

                    • 破坏类封装性,可以强制访问私有属性和方法。
                    • 性能开销较大,反射操作不受优化,可能影响程序性能。

                  反射技术在开发中非常实用,特别是在需要灵活配置和面对频繁需求变更的情况下。通过掌握反射的基本使用方法,可以在项目开发中提高效率,减少代码修改的频率。

    上一篇:JAVA反射机制
    下一篇:Java反射代码编写

    发表评论

    最新留言

    逛到本站,mark一下
    [***.202.152.39]2025年05月03日 07时41分20秒

    关于作者

        喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
    -- 愿君每日到此一游!

    推荐文章

    element 如何使用自定义icon图标 2025-03-29
    element-plus修改主题颜色 2025-03-29
    element-plus的el-date-picker日期范围选择控件,根据开始日期限定结束日期的可选范围为开始日期到开始日期+30天 2025-03-29
    18 个一线工作中常用 Shell 脚本【实用版】 2025-03-29
    element-ui:el-input输入数字-整数和小数 2025-03-29
    ElementUI-el-progress改变进度条颜色跟文字样式 2025-03-29
    element事件(change,click)不触发 2025-03-29
    ELK原理与介绍(转) 2025-03-29
    ELK学习笔记(三)单台服务器多节点部署 2025-03-29
    ELK应用日志收集实战 2025-03-29
    elTable火狐浏览器换行 2025-03-29
    15个Python数据处理技巧(非常详细)零基础入门到精通,收藏这一篇就够了 2025-03-29
    2023年深信服、奇安信、360等大厂网络安全校招面试真题合集(附答案),让你面试轻松无压力! 2025-03-29
    2024年全国程序员平均薪资排名:同样是程序员,为什么差这么多?零基础到精通,收藏这篇就够了 2025-03-29
    0基础成功转行网络安全工程师,年薪30W+,经验总结都在这(建议收藏) 2025-03-29
    100个电脑常用组合键大全(非常详细)零基础入门到精通,收藏这篇就够了 2025-03-29
    10个程序员可以接私活的平台 2025-03-29
    10个运维拿来就用的 Shell 脚本,用了才知道有多爽,零基础入门到精通,收藏这一篇就够了 2025-03-29
    10条sql语句优化的建议 2025-03-29
    10款宝藏编程工具!新手必备,大牛强烈推荐! 从零基础到精通,收藏这篇就够了! 2025-03-29