You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java反射调用invoke报object is not an instance of declaring class错误求助

错误原因

  • 拷贝方法逻辑错误:现有逻辑仅读取源对象(UserRequest)类的属性描述符,拿到的写方法是UserRequest类自身的set方法,却用目标对象User去调用该方法,User不属于UserRequest的实例,因此抛出类实例不匹配的异常。
  • 字段类型不兼容:User类的role字段为Role实体类型,而UserRequest类对应role字段为存储角色id的Long类型,二者类型不匹配,即便逻辑修正后直接拷贝也会抛出类型转换异常。

解决方案

方案1:使用成熟的Bean拷贝工具(推荐)

直接使用Spring提供的BeanUtils等成熟工具,避免手写工具类的逻辑漏洞,同时单独处理类型不匹配的role字段:

// 拷贝除role外的其他所有字段
BeanUtils.copyProperties(userRequest, user, "role");
// 单独根据请求中的roleId查询Role实例并赋值
Role role = roleRepository.findById(userRequest.getRole())
        .orElseThrow(() -> new IllegalArgumentException("非法的角色id"));
user.setRole(role);

注:User类自定义了setPassword方法会自动加密密码,拷贝时传入明文密码会自动加密,符合业务要求不需要额外处理。

方案2:修正自定义拷贝方法的逻辑

调整拷贝逻辑,分别读取源对象的读方法和目标对象同名字段的写方法,同时增加类型校验和特殊字段处理:

public static void copy(Object dest, Object source) throws IntrospectionException, IllegalArgumentException, IllegalAccessException,
        InvocationTargetException {
    BeanInfo sourceBeanInfo = Introspector.getBeanInfo(source.getClass());
    PropertyDescriptor[] sourcePdList = sourceBeanInfo.getPropertyDescriptors();
    
    // 缓存目标类所有属性描述符
    Map<String, PropertyDescriptor> destPdMap = new HashMap<>();
    BeanInfo destBeanInfo = Introspector.getBeanInfo(dest.getClass());
    for (PropertyDescriptor pd : destBeanInfo.getPropertyDescriptors()) {
        destPdMap.put(pd.getName(), pd);
    }

    for (PropertyDescriptor sourcePd : sourcePdList) {
        Method readMethod = sourcePd.getReadMethod();
        if (readMethod == null) {
            continue;
        }
        // 查找目标类同名属性
        PropertyDescriptor destPd = destPdMap.get(sourcePd.getName());
        if (destPd == null || destPd.getWriteMethod() == null) {
            continue;
        }
        Object val = readMethod.invoke(source);
        // 类型匹配直接赋值
        if (destPd.getPropertyType().isAssignableFrom(sourcePd.getPropertyType())) {
            destPd.getWriteMethod().invoke(dest, val);
            continue;
        }
        // 特殊处理role字段类型转换
        if ("role".equals(sourcePd.getName()) && val instanceof Long roleId) {
            // 这里可根据业务逻辑替换为实际的Role查询逻辑
            Role role = new Role();
            role.setId(roleId);
            destPd.getWriteMethod().invoke(dest, role);
        }
    }
}

内容的提问来源于stack exchange,提问作者Hunny Chawla

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.13 12:42:03