Can not set java.lang.String field copyField.SrcObj.strField1 to java.lang.reflect.Field
时间: 2024-10-18 15:03:33 浏览: 17
当你尝试通过`java.lang.reflect.Field`直接修改一个对象的字段时,可能会遇到这个错误,因为`setAccessible(true)`并没有改变默认访问控制权限,而`String`类型的字段通常是final和不可变的,所以不允许直接通过`Field.set()`方法进行赋值。
对于`String`类型的字段,它的值通常是在构造函数中确定的,并且为了防止程序意外修改字符串常量池,它们被声明为final,这意味着它们一旦初始化就不能再改变。如果你试图更改的是`final`字段,你需要检查是否有其他途径可以修改,比如通过对象的setter方法,或者它是否是一个可变的内部类的引用。
例如,如果`SrcObj`有一个`strField1`,而`copyField`不是`SrcObj`的实例,你可能需要这样做:
```java
SrcObj srcObj = ...; // 获取源对象实例
copyField.set(srcObj, "new value"); // 如果strField1是可变对象,则可以这样赋值
// 或者,如果strField1是不可变字符串,你可能需要通过其他方式(如全局变量、配置等)传递新的值
copyField.setSrcObjValue(srcObj, "new value");
```
相关问题
package com.bjsasc.finance.common.utils; import java.beans.BeanInfo; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; public class JavaBeanUtil { /** * * @param source 被复制的实体类对象 * @param to 复制完后的实体类对象 * @throws Exception */ public static void Copy(Object source, Object to) throws Exception { // 获取属性 BeanInfo sourceBean = Introspector.getBeanInfo(source.getClass(),java.lang.Object.class); PropertyDescriptor[] sourceProperty = sourceBean.getPropertyDescriptors(); BeanInfo destBean = Introspector.getBeanInfo(to.getClass(),java.lang.Object.class); PropertyDescriptor[] destProperty = destBean.getPropertyDescriptors(); try { for (int i = 0; i < sourceProperty.length; i++) { for (int j = 0; j < destProperty.length; j++) { if (sourceProperty[i].getName().equals(destProperty[j].getName())) { // 调用source的getter方法和dest的setter方法 destProperty[j].getWriteMethod().invoke(to,sourceProperty[i].getReadMethod().invoke(source)); break; } } } } catch (Exception e) { throw new Exception("属性复制失败:" + e.getMessage()); } } /** * Pojo -> Map<String, Object> * @param obj * @return * @throws Exception */ public static Map<String,Object> object2Map(Object obj)throws Exception{ Map<String,Object> map =new HashMap<>(); Field[] fields = obj.getClass().getDeclaredFields(); for(Field field:fields){ field.setAccessible(true); map.put(field.getName(), field.get(obj)); } return map; } } 帮我优化下这个代码,考虑对象中有对象和对象集合的情况
下面是对 JavaBeanUtil 类的优化:
1. 添加私有构造函数,避免该类被实例化。
2. 在 Copy 方法中添加对参数为空的判断,避免空指针异常。
3. 在 Copy 方法中,使用 Map 存储类属性名和对应的属性描述器,避免重复获取,提高效率。
4. 改进 Copy 方法,支持复制对象中包含的对象和对象集合。
5. 将 object2Map 方法改为 genericObjectToMap,更好地传达其作用。
6. genericObjectToMap 方法使用泛型,支持更多类型的对象。
7. 在 genericObjectToMap 方法中,使用 Map 存储类属性名和对应的属性值,避免重复获取,提高效率。
8. genericObjectToMap 方法中添加对参数为空的判断。
下面是优化后的代码:
```
package com.bjsasc.finance.common.utils;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public final class JavaBeanUtil {
private JavaBeanUtil() {
throw new AssertionError("Cannot instantiate the utility class");
}
/**
* 复制 source 对象的属性到 to 对象中
*
* @param source 被复制的实体类对象
* @param to 复制完后的实体类对象
* @throws Exception
*/
public static void copy(Object source, Object to) throws Exception {
if (source == null || to == null) {
throw new IllegalArgumentException("参数不能为空");
}
// 获取属性
BeanInfo sourceBean = Introspector.getBeanInfo(source.getClass(), java.lang.Object.class);
PropertyDescriptor[] sourceProperty = sourceBean.getPropertyDescriptors();
BeanInfo destBean = Introspector.getBeanInfo(to.getClass(), java.lang.Object.class);
PropertyDescriptor[] destProperty = destBean.getPropertyDescriptors();
Map<String, PropertyDescriptor> destPropMap = new HashMap<>();
for (PropertyDescriptor desc : destProperty) {
destPropMap.put(desc.getName(), desc);
}
for (PropertyDescriptor srcDesc : sourceProperty) {
PropertyDescriptor destDesc = destPropMap.get(srcDesc.getName());
if (destDesc != null && destDesc.getWriteMethod() != null && srcDesc.getReadMethod() != null) {
Type srcType = srcDesc.getReadMethod().getGenericReturnType();
Type destType = destDesc.getWriteMethod().getGenericParameterTypes()[0];
if (isAssignable(srcType, destType)) {
Object value = srcDesc.getReadMethod().invoke(source);
if (value != null) {
if (value instanceof List) {
List<?> srcList = (List<?>) value;
List<Object> destList = new ArrayList<>();
for (Object srcObj : srcList) {
Object destObj = srcObj.getClass().newInstance();
copy(srcObj, destObj);
destList.add(destObj);
}
value = destList;
} else {
Object destObj = value.getClass().newInstance();
copy(value, destObj);
value = destObj;
}
destDesc.getWriteMethod().invoke(to, value);
}
}
}
}
}
/**
* 将对象转换为 Map
*
* @param obj
* @return
* @throws Exception
*/
public static Map<String, Object> genericObjectToMap(Object obj) throws Exception {
if (obj == null) {
throw new IllegalArgumentException("参数不能为空");
}
Map<String, Object> map = new HashMap<>();
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
Type type = field.getGenericType();
Object value = field.get(obj);
if (value == null) {
continue;
}
if (type instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType) type;
Type[] argTypes = pType.getActualTypeArguments();
if (argTypes.length == 1 && argTypes[0] instanceof Class && List.class.isAssignableFrom(field.getType())) {
List<?> list = (List<?>) value;
List<Map<String, Object>> listMap = new ArrayList<>();
for (Object objElem : list) {
listMap.add(genericObjectToMap(objElem));
}
value = listMap;
}
} else {
if (!isAssignable(type, Map.class)) {
map.put(field.getName(), value);
}
}
}
return map;
}
private static boolean isAssignable(Type srcType, Type destType) {
if (srcType.equals(destType)) {
return true;
}
if (destType.equals(Object.class)) {
return true;
}
if (destType instanceof Class && srcType instanceof Class) {
Class<?> destClass = (Class<?>) destType;
Class<?> srcClass = (Class<?>) srcType;
if (destClass.isAssignableFrom(srcClass)) {
return true;
}
}
return false;
}
}
```
上述代码改进了原有的 copy 方法,支持复制对象中包含的对象和对象集合,同时转换对象到 Map 的方法 genericObjectToMap 也进行了优化,支持更多类型的对象。
BeanUtil.copyProperties中的ignoreProperties 怎么使用
`BeanUtil.copyProperties`是一个常用的方法,用于从一个属性源复制属性到另一个目标对象。其中的`ignoreProperties`参数允许你指定在复制过程中忽略哪些属性,这对于处理不需要同步的属性或者避免数据冲突很有用。
当你提供一个字符串数组、`Set`或`Properties`给`ignoreProperties`,它会跳过这些列表中的属性名字不做复制。例如:
```java
String[] ignoreProps = {"password", "privateInfo"};
BeanUtil.copyProperties(srcObj, destObj, ignoreProps);
```
这里,源对象`srcObj`的`password`和`privateInfo`字段将不会被复制到目标对象`destObj`。
如果你有一个自定义的`Properties`对象:
```java
Properties ignoreProps = new Properties();
ignoreProps.setProperty("password", "");
ignoreProps.setProperty("privateInfo", "");
BeanUtil.copyProperties(srcObj, destObj, ignoreProps.getProperties());
```
同样,这两个属性会被忽略。
阅读全文