反射中对类的属性、方法、构造器的相关操作

反射中对类的属性、方法、构造器的相关操作


操作的实体类

package com.sai.reflet;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author cuiss
 * @Date 2025-03-24 09:37
 * @Description
 **/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {

    private Integer id;

    private String name;
}

测试代码

package com.sai.reflet;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author cuiss
 * @Date 2025-03-24 09:38
 * @Description 测试 反射中对类的属性、方法、构造器的相关操作
 **/
@Slf4j
public class TestUser {

    static User user = new User(1, "张三");

    /**
     * 通过反射获取类的 指定属性和值
     */
    @org.junit.jupiter.api.Test
    public void test1() {
        try {
            // 1. 获取Class对象
            Class<? extends User> reClass = User.class;

            // 2. 获取私有Field对象
            Field nameField = reClass.getDeclaredField("name");

            // 3. 设置可访问性(对私有属性必须)
            nameField.setAccessible(true);

            // 4. 创建实例(如果是静态属性则不需要)--- 这里引用静态已经创建好的实例
            User entity = user;

            // 5. 获取属性值
            Object value = nameField.get(entity);

            log.info("获取Class对象的指定私有属性值:name {}", value);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 通过反射获取类的 所有属性和值
     */
    @org.junit.jupiter.api.Test
    public void test2() {
        Class<? extends User> reClass = user.getClass();

        log.info("类名:{}", reClass.getName());
        log.info("所有属性及值:");

        // 获取所有声明的字段(包括私有字段)
        Field[] fields = reClass.getDeclaredFields();
        for (Field field : fields) {
            try {
                // 设置可访问性以访问私有字段
                field.setAccessible(true);

                // 获取字段名
                String name = field.getName();

                // 获取字段值
                Object value = field.get(user);

                // 获取字段类型
                Class<?> type = field.getType();

                // 打印字段信息
                log.info("字段名: {} 类型: {} 值: {}", name, type.getSimpleName(), value);
            } catch (IllegalAccessException e) {
                System.out.println("无法访问字段: " + field.getName() + " - " + e.getMessage());
            }
        }
    }

    /**
     * 通过反射获取类的 指定方法并调用
     */
    @org.junit.jupiter.api.Test
    public void test3() {
        try {
            // 1. 获取Class对象
            Class<? extends User> reClass = user.getClass();

            // 2. 获取指定方法(getName)
            Method getName = reClass.getMethod("getName");

            // 3. 调用方法
            Object value = getName.invoke(user);

            // 4. 输出结果
            log.info("通过反射获取类的 指定方法(getName)并调用:{}", value);
        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 通过反射获取类的 所有方法并调用
     */
    @org.junit.jupiter.api.Test
    public void test4() {
        try {
            // 1. 获取Class对象
            Class<? extends User> reClass = user.getClass();

            // 2. 获取指定方法(getName)
            //    获取所有声明的方法(不包括继承的方法) reClass.getDeclaredMethods();
            Method[] getNames = reClass.getMethods();
            log.info("获取类:{} 的所有公共方法", reClass.getName());

            // 3. 循环处理
            for (Method method : getNames) {
                System.out.println("方法名: " + method.getName());

                // 如果是getName方法就调用
                if ("getName".equals(method.getName()) &&
                        method.getParameterCount() == 0) {

                    Object result = method.invoke(user);
                    System.out.println("调用结果: " + result);
                }
            }
        } catch (InvocationTargetException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 通过反射获取类的 构造器并实例化
     * 方式一:使用 Class.newInstance()(已废弃,Java 9+ 不建议使用)
     * 只能调用无参构造器,且构造器必须是可访问的(非 private)。
     * 如果无参构造器不存在或不可访问,会抛出 InstantiationException 或 IllegalAccessException。
     */
    @org.junit.jupiter.api.Test
    public void test5() {
        try {
            // 方式一:.class
            Class<User> userClass = User.class;
            User user = userClass.newInstance();
            log.info("通过反射获取类的 构造器并实例化  无参构造  方式一:  User:{}", user);

            // 方式二:forName(String className)
            Class<?> userClass2 = Class.forName("com.sai.reflet.User");
            User user2 = (User) userClass2.newInstance();
            log.info("通过反射获取类的 构造器并实例化  无参构造  方式二:  User:{}", user2);
        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 通过反射获取类的 构造器并实例化
     * 方式二:使用 Constructor.newInstance()(推荐方式)
     * getConstructor(Class<?>... paramTypes):获取公共构造器(public)。
     * getDeclaredConstructor(Class<?>... paramTypes):获取任意权限的构造器(包括 private)。
     * 如果构造器是 private 的,需要先调用 constructor.setAccessible(true)。
     */
    @org.junit.jupiter.api.Test
    public void test6() {
        try {
            // 无参构造
            Class<User> userClass = User.class;
            Constructor<User> constructor = userClass.getConstructor();
            User user = constructor.newInstance();

            // 有参构造
            Class<User> userClassY = User.class;
            Constructor<User> constructorY = userClassY.getConstructor(Integer.class, String.class);
            User userY = constructorY.newInstance(666, "豹子");

            log.info("无参构造  User:{}", user);
            log.info("有参构造  User:{}", userY);
        } catch (NoSuchMethodException | InvocationTargetException | InstantiationException |
                 IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 通过反射获取类的 属性的 可访问标志
     */
    @org.junit.jupiter.api.Test
    public void test7() {
        try {
            // 1. 获取Class对象
            Class<? extends User> reClass = User.class;

            // 2. 获取私有Field对象
            Field nameField = reClass.getDeclaredField("name");

            // 3. 检查并设置可访问标志
            boolean accessible = nameField.isAccessible();
            if (!accessible) {
                nameField.setAccessible(true);
            }
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 通过反射获取类的 方法的 可访问标志
     */
    @org.junit.jupiter.api.Test
    public void test8() {
        try {
            // 1. 获取Class对象
            Class<? extends User> reClass = user.getClass();

            // 2. 获取指定方法(getName)
            Method getName = reClass.getMethod("getName");

            // 3. 检查并设置可访问标志
            boolean accessible = getName.isAccessible();
            if (!accessible) {
                getName.setAccessible(true);
            }
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

}
<think>我们正在讨论Java反射构造器的获取与调用。用户已经了解了基本操作,现在希望了解如何利用工具方法简化反射操作。 引用[4]中提供了一个工具示例,但用户更关注的是如何调用构造器相关的工具方法进行实例化或操作。 实际上,Java标准库中并没有专门针对构造器的工具,但我们可以通过Apache Commons Lang或Spring Framework等第三方库的工具来简化操作。 不过,用户可能更希望看到如何自己编写工具方法,或者使用标准库结合反射API实现。 核心思路: 1. 获取构造器(Constructor对象) 2. 使用Constructor对象的newInstance方法创建实例 3. 可以封装这些操作为一个工具 根据引用[4]中的UserISI,我们可以编写一个工具,实现通过反射创建对象,并可能设置属性。 但用户问题明确是“构造器相关的工具方法”,所以重点在构造器的获取和调用。 我们可以设计一个工具,包含以下方法: - 根据名和参数型获取构造器 - 根据构造器和参数创建实例 - 批量获取构造器并选择匹配的构造器 然而,实际中,我们更常用的是直接调用Constructor.newInstance(),但为了简化异常处理和构造器查找,可以封装。 步骤: 1. 创建工具ReflectionUtils 2. 提供获取构造器方法(考虑异常处理) 3. 提供创建实例的方法(包括无参和有参) 注意:引用[3]提到了无参构造方法中调用有参构造,但那是构造器重载的问题,与反射工具关系不大。 下面我们设计一个简单的工具,并演示如何使用。</think>### Java反射调用构造器的工具方法实践指南 根据引用[1]和引用[4]的示例,以下是使用反射获取构造器后,通过工具方法进行实例化与操作的完整方案: #### 一、核心工具方法封装 ```java import java.lang.reflect.*; public class ReflectionUtils { // 根据参数型获取构造器 public static Constructor<?> getConstructor(Class<?> clazz, Class<?>... paramTypes) throws NoSuchMethodException { return clazz.getDeclaredConstructor(paramTypes); } // 创建实例(自动处理访问权限) public static Object createInstance(Constructor<?> constructor, Object... args) throws Exception { constructor.setAccessible(true); // 解除私有访问限制[^1] return constructor.newInstance(args); } // 批量获取所有构造器 public static Constructor<?>[] getAllConstructors(Class<?> clazz) { return clazz.getDeclaredConstructors(); } // 打印构造器详情 public static void printConstructorInfo(Constructor<?> constructor) { System.out.println("构造器: " + constructor.getName()); System.out.println("参数数量: " + constructor.getParameterCount()); for (Parameter param : constructor.getParameters()) { System.out.println(" └ 参数型: " + param.getType().getSimpleName()); } } } ``` #### 二、工具使用示例(基于引用[4]的UserISI) ```java public class Main { public static void main(String[] args) throws Exception { // 1. 获取Class对象 Class<?> userClass = Class.forName("com.example.UserISI"); // 2. 获取特定构造器(带三个参数) Constructor<?> threeParamConstructor = ReflectionUtils.getConstructor( userClass, int.class, String.class, int.class ); // 3. 创建实例 Object user1 = ReflectionUtils.createInstance( threeParamConstructor, 101, "张三", 30 ); System.out.println("创建实例: " + user1); // 4. 获取无参构造器 Constructor<?> noArgConstructor = ReflectionUtils.getConstructor(userClass); Object user2 = ReflectionUtils.createInstance(noArgConstructor); System.out.println("空实例: " + user2); // 5. 分析所有构造器 System.out.println("\n=== 构造器分析 ==="); for (Constructor<?> con : ReflectionUtils.getAllConstructors(userClass)) { ReflectionUtils.printConstructorInfo(con); } } } ``` #### 三、执行结果示例 ``` 创建实例: UserISI{userId=101, username='张三', age=30} 空实例: UserISI{userId=0, username='null', age=null} === 构造器分析 === 构造器: com.example.UserISI 参数数量: 0 构造器: com.example.UserISI 参数数量: 2 └ 参数型: String └ 参数型: int 构造器: com.example.UserISI 参数数量: 3 └ 参数型: int └ 参数型: String └ 参数型: int ``` #### 四、高级应用场景 1. **动态对象创建框架** ```java // 根据配置文件创建对象 Properties config = loadConfig(); Object instance = ReflectionUtils.createInstance( getConstructor(Class.forName(config.getProperty("className"))), parseArguments(config.getProperty("constructorArgs")) ); ``` 2. **构造器参数自动匹配** ```java public static Object smartCreate(Class<?> clazz, Object... args) throws Exception { for (Constructor<?> con : clazz.getDeclaredConstructors()) { if (isParamMatch(con, args)) { // 自定义参数匹配逻辑 return ReflectionUtils.createInstance(con, args); } } throw new NoSuchMethodException("无匹配构造器"); } ``` 3. **单例模式安全检测** ```java public static void checkSingletonSafety(Class<?> clazz) { Constructor<?>[] constructors = ReflectionUtils.getAllConstructors(clazz); if (constructors.length > 1) { throw new IllegalStateException("单例应只有一个构造器"); } if (!Modifier.isPrivate(constructors[0].getModifiers())) { throw new IllegalStateException("单例构造器必须是私有的"); } } ``` > 关键点:通过`setAccessible(true)`可突破私有构造器的访问限制,这是实现依赖注入等高级特性的基础[^1]。但需注意安全风险,建议在受控环境下使用。 #### 五、性能优化建议 1. **构造器缓存** ```java private static final Map<String, Constructor<?>> CONSTRUCTOR_CACHE = new ConcurrentHashMap<>(); public static Constructor<?> getCachedConstructor(String className, Class<?>... paramTypes) throws Exception { String key = className + Arrays.toString(paramTypes); return CONSTRUCTOR_CACHE.computeIfAbsent(key, k -> getConstructor(Class.forName(className), paramTypes) ); } ``` 2. **异常统一处理** ```java public static Object safeCreate(Constructor<?> constructor, Object... args) { try { return createInstance(constructor, args); } catch (InvocationTargetException e) { throw new RuntimeException("构造器执行异常", e.getTargetException()); } catch (InstantiationException e) { throw new RuntimeException("抽象无法实例化", e); } catch (IllegalAccessException e) { throw new RuntimeException("访问权限不足", e); } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值