Java应用运行时,如何动态加载类信息?实例化类?你可以使用Java反射机制

本文深入探讨Java反射机制,介绍如何在运行时加载类信息和实例化对象。通过Class.forName()和Constructor.newInstance()方法实现类的加载与实例化。详细讲解了反射的应用场景,如拓展特性、类浏览器、调试器和测试工具,并通过代码示例展示反射在类、构造函数、变量和方法上的应用。同时,文章还讨论了数组和枚举的反射,以及Modifier类的相关信息。
摘要由CSDN通过智能技术生成

反射机制

官方定义为: Reflection is commonly used by programs which require the ability to examine or modify the runtime behavior of applications running in the Java virtual machine.

实际使用中,反射是,在Java虚拟机上处于运行时的应用中,能够动态加载类,实例化类,以及访问、修改类的属性和行为。

补充

  • Java应用会经过编译时和运行时。运行时,由加载过程和执行主函数步骤组成。
  • Java加载过程包括加载、链接、初始化和绑定native实现方法等步骤。
  • Class.forName() 是将类加载进入内存,此时,虚拟机中并未存在该类的实例,而需要通过构造函数类ConstructornewInstance() 方法进行实例化。

应用场景

1. 拓展特性
应用程序可以使用用户定义的外部类,通过使用外部类的完全限定名称,创建可扩展性对象的实例。符合大多数的使用情况,例如Spring MVC用了反射。
示例

  • Spring框架中动态代理使用反射创建代理类,例如工具类 org.springframework.cglib.core.ReflectUtils将jdk的反射功能封装起来。
  • Spring框架中org.springframework.util.ClassUtils将java反射功能封装为工具类,提供Spring IoC和Spring AOP机制加载类和创建类实例的方法。

2. 类浏览器和可视化环境
类浏览器需要能够枚举出类的成员。可视化开发环境可受益于,利用反射中可用的类型信息帮助开发者写出正确的代码
示例

  • Gradleorg.gradle.internal.impldep.bsh.util.ClassBrowser 通过反射获取所有的类信息。

3. 调试器和测试工具
调试器需要能够检测类的私有成员。测试工具可以利用反射系统地调用一个类中定义的暴露的APIs集,以确保测试集的高覆盖率。
示例

  • Java测试框架JUnitorg.junit.internal.Classes封装java反射,ReflectiveRuntimeMXBean通过封装的工具类使用java反射获取MXBean。

代码演示

下面提供一个演示类ReflectDemo和类Person,以及main方法演示使用Class反射相关方法。这篇文章都基于这一小节的代码,


/**
 * 演示Java的Reflect反射功能
 * */
public class ReflectDemo {
   
	
	// 地区枚举类
    enum Region {
   
        ASIA, AFRICA, AMERICA, EUROPE
    }

    /*
    *  演示反射功能
    * */
    public static void main(String[] args){
   
        try {
   
            // 模拟获取指定类的全限定名,仅供演示使用,实际工作中根据情况获取
            String classFullQualifiedPath = getDemoClassPath();

            //1.类反射
            Class clazz = Class.forName(classFullQualifiedPath);
            //通过获取指定形参类型顺序数组获取构造函数,调用newInstance传入相应的实参列表进行实例化
            Object newInstance = clazz.getConstructor(String.class, String.class, Region.class).newInstance("OneKnows", "178cm", Region.ASIA);
            if (newInstance instanceof Person person)
                out.format("New instance: %s%nname: %s%n%n", person, person.name);
            else
                out.format("New instance: %s%nname: %s%n", newInstance);
            // 2. 成员反射
            // 2.1 构造器反射
            Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
            printInfos(declaredConstructors);
            tryConstructorFeatures(declaredConstructors);
            // 2.2 方法反射
            Method[] declaredMethods = clazz.getDeclaredMethods();
            printInfos(declaredMethods);
            tryMethodFeatures(declaredMethods,newInstance);
            // 2.3 变量反射
            Field[] declaredFields = clazz.getDeclaredFields();
            printInfos(declaredFields);
            tryFieldFeatures(declaredFields, newInstance);
            //3. 枚举反射
            String enumClassFullQualifiedPath = getEnumDemoClassPath(); // 模拟获取指定枚举类的全限定名,仅供演示使用,实际工作中根据情况获取
            Class<?> enumClazz = Class.forName(enumClassFullQualifiedPath);
            //判断是否为枚举类
            if (enumClazz.isEnum()){
   
                Object[] enumConstants = enumClazz.getEnumConstants(); // 获取枚举常量数组
                printInfos(enumConstants);
            }
        } catch (Exception e) {
   
            e.printStackTrace(out);
        }
    }

    public static void tryConstructorFeatures(Constructor[] declaredConstructors){
   
        //隐藏具体实现
    }

    public static void tryMethodFeatures(Method[] declaredMethods, Object newInstance){
   
        //隐藏具体实现
    }

    public static void tryFieldFeatures(Field[] fields, Object newInstance){
   
        //隐藏具体实现
    }

    public static void printInfos(Object[] objects){
   
        if (objects==null)return; //若为null,则结束
        for (Object object : objects) {
   
            out.format("Name: %s,%nValue: %s%n%n",object.getClass(), object);
        }
    }

    // 给演示用,提供演示类的全限定路径名
    public static String getDemoClassPath(){
   
        return Person.class.getName();
    }
    public static String getEnumDemoClassPath(){
   
        return Region
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一知先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值