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
相关产品推荐
相关产品推荐

