请参阅以下课程
public class Parent {
private String name;
private int age;
private Date birthDate;
// getters and setters
}
假设我创建了一个父对象,如下所示
Parent parent = new Parent();
parent.setName("A meaningful name");
parent.setAge(20);
根据上面的代码注意,birthDate属性为null。现在我想从父对象复制到另一个非空属性。像
这样的东西SomeHelper.copyNonNullProperties(parent, anotherParent);
我需要它,因为我想更新anotherParent对象而不用空值覆盖它的非null。
你知道这样的帮助吗?
我接受最少的代码作为回答是否没有帮助
的问候,
答案 0 :(得分:81)
我认为你已经有了一个解决方案,因为你问过很多时间。但是,它没有标记为已解决,也许我可以帮助其他用户。
您是否尝试过定义BeanUtilsBean
包的org.commons.beanutils
的子类?实际上,BeanUtils
使用此类,因此这是对dfa提出的解决方案的改进。
检查该类的source code,我认为您可以通过检查空值来覆盖copyProperty
方法,如果值为null,则不执行任何操作。
这样的事情:
package foo.bar.copy;
import java.lang.reflect.InvocationTargetException;
import org.apache.commons.beanutils.BeanUtilsBean;
public class NullAwareBeanUtilsBean extends BeanUtilsBean{
@Override
public void copyProperty(Object dest, String name, Object value)
throws IllegalAccessException, InvocationTargetException {
if(value==null)return;
super.copyProperty(dest, name, value);
}
}
然后你可以实例化一个NullAwareBeanUtilsBean
并用它来复制你的bean,例如:
BeanUtilsBean notNull=new NullAwareBeanUtilsBean();
notNull.copyProperties(dest, orig);
答案 1 :(得分:3)
使用PropertyUtils(commons-beanutils)
for (Map.Entry<String, Object> e : PropertyUtils.describe(parent).entrySet()) {
if (e.getValue() != null && !e.getKey().equals("class")) {
PropertyUtils.setProperty(anotherParent, e.getKey(), e.getValue());
}
}
Java8中的:
PropertyUtils.describe(parent).entrySet().stream()
.filter(e -> e.getValue() != null)
.filter(e -> ! e.getKey().equals("class"))
.forEach(e -> {
try {
PropertyUtils.setProperty(anotherParent, e.getKey(), e.getValue());
} catch (Exception e) {
// Error setting property ...;
}
});
答案 2 :(得分:2)
只需使用您自己的复制方法:
void copy(Object dest, Object source) throws IntrospectionException, IllegalArgumentException, IllegalAccessException,
InvocationTargetException {
BeanInfo beanInfo = Introspector.getBeanInfo(source.getClass());
PropertyDescriptor[] pdList = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor pd : pdList) {
Method writeMethod = null;
Method readMethod = null;
try {
writeMethod = pd.getWriteMethod();
readMethod = pd.getReadMethod();
} catch (Exception e) {
}
if (readMethod == null || writeMethod == null) {
continue;
}
Object val = readMethod.invoke(source);
writeMethod.invoke(dest, val);
}
}
答案 3 :(得分:2)
如果你的setter的返回类型不是void,那么Apache的BeanUtils就无法工作了。所以结合两者。
package cn.corpro.bdrest.util;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.ConvertUtilsBean;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.springframework.beans.BeanUtils;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
/**
* Author: BaiJiFeiLong@gmail.com
* DateTime: 2016/10/20 10:17
*/
public class MyBeanUtils {
public static void copyPropertiesNotNull(Object dest, Object orig) throws InvocationTargetException, IllegalAccessException {
NullAwareBeanUtilsBean.getInstance().copyProperties(dest, orig);
}
private static class NullAwareBeanUtilsBean extends BeanUtilsBean {
private static NullAwareBeanUtilsBean nullAwareBeanUtilsBean;
NullAwareBeanUtilsBean() {
super(new ConvertUtilsBean(), new PropertyUtilsBean() {
@Override
public PropertyDescriptor[] getPropertyDescriptors(Class<?> beanClass) {
return BeanUtils.getPropertyDescriptors(beanClass);
}
@Override
public PropertyDescriptor getPropertyDescriptor(Object bean, String name) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
return BeanUtils.getPropertyDescriptor(bean.getClass(), name);
}
});
}
public static NullAwareBeanUtilsBean getInstance() {
if (nullAwareBeanUtilsBean == null) {
nullAwareBeanUtilsBean = new NullAwareBeanUtilsBean();
}
return nullAwareBeanUtilsBean;
}
@Override
public void copyProperty(Object bean, String name, Object value) throws IllegalAccessException, InvocationTargetException {
if (value == null) return;
super.copyProperty(bean, name, value);
}
}
}
答案 4 :(得分:1)
经过多年寻找解决方案后,我来到了这里,使用简单的Java反射来实现它。希望对您有帮助!
public static void copyDiff(Product destination, Product source) throws
IllegalAccessException, NoSuchFieldException {
for (Field field : source.getClass().getDeclaredFields()) {
field.setAccessible(true);
String name = field.getName();
Object value = field.get(source);
//If it is a non null value copy to destination
if (null != value)
{
Field destField = destination.getClass().getDeclaredField(name);
destField.setAccessible(true);
destField.set(destination, value);
}
System.out.printf("Field name: %s, Field value: %s%n", name, value);
}
}
答案 5 :(得分:0)
您可以使用Apache Common BeanUtils,更具体地说the copyProperties helper in BeanUtils class:
BeanUtils.copyProperties(parent, anotherParent);
但是为什么你只想要复制非空属性?如果parent
中的某个属性为null,只需复制它,你在anotherParent
中也有空吗?
猜猜......你想用另一个bean更新bean吗?
答案 6 :(得分:0)
我知道这个问题很老了,但我认为以下答案可能对某人有用。
如果您使用Spring,可以尝试以下选项。
import java.beans.PropertyDescriptor;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
/**
* Helper class to extract property names from an object.
*
* @Threadsafe
*
* @author arun.bc
*
*/
public class PropertyUtil {
/**
* Gets the properties which have null values from the given object.
*
* @param - source object
*
* @return - String array of property names.
*/
public static String[] getNullPropertiesString(Object source) {
Set<String> emptyNames = getNullProperties(source);
String[] result = new String[emptyNames.size()];
return emptyNames.toArray(result);
}
/**
* Gets the properties which have null values from the given object.
*
* @param - source object
*
* @return - Set<String> of property names.
*/
public static Set<String> getNullProperties(Object source) {
final BeanWrapper src = new BeanWrapperImpl(source);
PropertyDescriptor[] pds = src.getPropertyDescriptors();
Set<String> emptyNames = new HashSet<String>();
for (PropertyDescriptor pd : pds) {
Object srcValue = src.getPropertyValue(pd.getName());
if (srcValue == null)
emptyNames.add(pd.getName());
}
return emptyNames;
}
/**
* Gets the properties which are not null from the given object.
*
* @param - source object
*
* @return - Set<String> array of property names.
*/
public static Set<String> getNotNullProperties(Object source) {
final BeanWrapper src = new BeanWrapperImpl(source);
PropertyDescriptor[] pds = src.getPropertyDescriptors();
Set<String> names = new HashSet<String>();
for (PropertyDescriptor pd : pds) {
Object srcValue = src.getPropertyValue(pd.getName());
if (srcValue != null)
names.add(pd.getName());
}
return names;
}
}
您可以再次使用PropertyDescriptor和上述方法中的Set来修改对象。
答案 7 :(得分:0)
这是我的改编,用于复制非null属性,包括使用Spring BeanUtils忽略属性。
package com.blah;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import java.beans.PropertyDescriptor;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Nonnull;
/**
* brett created on 10/1/20.
* <p>
* Modified from: https://codippa.com/skip-null-properties-spring-beanutils/
*/
public final class NullAwareBeanUtils {
private NullAwareBeanUtils() {}
/**
* Copies non-null properties from one object to another.
*
* @param source
* @param destination
* @param ignoreProperties
*/
public static void copyNonNullProperties(Object source, Object destination, String... ignoreProperties) {
final Set<String> ignoreAllProperties = new HashSet<>();
ignoreAllProperties.addAll(getPropertyNamesWithNullValue(source));
ignoreAllProperties.addAll(Arrays.asList(ignoreProperties));
BeanUtils.copyProperties(source, destination, ignoreAllProperties.toArray(new String[]{}));
}
@Nonnull
private static Set<String> getPropertyNamesWithNullValue(Object source) {
final BeanWrapper sourceBeanWrapper = new BeanWrapperImpl(source);
final java.beans.PropertyDescriptor[] propertyDescriptors = sourceBeanWrapper.getPropertyDescriptors();
final Set<String> emptyNames = new HashSet();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
// Check if value of this property is null then add it to the collection
Object propertyValue = sourceBeanWrapper.getPropertyValue(propertyDescriptor.getName());
if (propertyValue != null) continue;
emptyNames.add(propertyDescriptor.getName());
}
return emptyNames;
}
}