Java 为了将非空属性从对象复制到另一个对象的助手?(爪哇)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1301697/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Helper in order to copy non null properties from object to another ? (Java)
提问by Arthur Ronald
See the following class
看下面的课
public class Parent {
private String name;
private int age;
private Date birthDate;
// getters and setters
}
Suppose i have created a parent object as follows
假设我创建了一个父对象如下
Parent parent = new Parent();
parent.setName("A meaningful name");
parent.setAge(20);
Notice according to code above birthDate property is null. Now i want to copy ONLY non null properties from parent object to another. Something like
请注意,根据上面的代码birthDate 属性为空。现在我只想将非空属性从父对象复制到另一个。就像是
SomeHelper.copyNonNullProperties(parent, anotherParent);
I need it because i want to update anotherParent object without overrides its non null with null values.
我需要它,因为我想更新 anotherParent 对象而不用空值覆盖其非空值。
Do you know some helper like this one ?
你认识这样的帮手吗?
I accept minimal code as answer whether no helper in mind
我接受最少的代码作为答案是否没有帮助
regards,
问候,
采纳答案by SergiGS
I supose you already have a solution, since a lot of time has happened since you asked. However, it is not marked as solved, and maybe I can help other users.
我假设您已经有了解决方案,因为自从您提出要求以来已经发生了很多时间。但是,它没有标记为已解决,也许我可以帮助其他用户。
Have you tried by defining a subclass of the BeanUtilsBeanof the org.commons.beanutilspackage? Actually, BeanUtilsuses this class, so this is an improvement of the solution proposed by dfa.
你有没有定义的一个子类试过BeanUtilsBean了的org.commons.beanutils包?实际BeanUtils使用了这个类,所以这是对dfa提出的方案的改进。
Checking at the source codeof that class, I think you can overwrite the copyPropertymethod, by checking for null values and doing nothing if the value is null.
检查该类的源代码,我认为您可以copyProperty通过检查空值并在值为空时不执行任何操作来覆盖该方法。
Something like this :
像这样的事情:
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);
}
}
Then you can just instantiate a NullAwareBeanUtilsBeanand use it to copy your beans, for example:
然后你可以实例化 aNullAwareBeanUtilsBean并使用它来复制你的 bean,例如:
BeanUtilsBean notNull=new NullAwareBeanUtilsBean();
notNull.copyProperties(dest, orig);
回答by dfa
you can use Apache Common BeanUtils, more specifically the copyProperties helper in BeanUtils class:
您可以使用Apache Common BeanUtils,更具体地说是 BeanUtils 类中的 copyProperties 助手:
BeanUtils.copyProperties(parent, anotherParent);
however why do you want copy only non-null properties? if a property in parentis null, by simply copying it you have null also in anotherParentright?
但是为什么你只想复制非空属性?如果一个属性parent为空,通过简单地复制它,你也有空值,anotherParent对吗?
Just guessing... you want to update a bean with another bean?
只是猜测……您想用另一个 bean 更新一个 bean?
回答by Mohsen
Simply use your own copy method:
只需使用您自己的复制方法:
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);
}
}
回答by Arun B Chandrasekaran
I know the fact that this question is pretty old, but I thought the below answer may be useful for someone.
我知道这个问题已经很老了,但我认为以下答案可能对某人有用。
If you use Spring, you may try the below option.
如果您使用 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;
}
}
Again you may use PropertyDescriptor and the Set from the above methods to modify the object.
同样,您可以使用上述方法中的 PropertyDescriptor 和 Set 来修改对象。
回答by BaiJiFeiLong
If your setter's return type is not void, BeanUtils of Apache will not work, spring can. So combine the two.
如果你的setter的返回类型不是void,Apache的BeanUtils就不行,spring可以。所以将两者结合起来。
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: [email protected]
* 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);
}
}
}
回答by Lorenzo Luconi Trombacchi
Using PropertyUtils (commons-beanutils)
使用 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());
}
}
in Java8:
在 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 ...;
}
});
回答by samairtimer
I landed here after many years finding a solution, used simple java reflection to achieve it. Hope it helps!
经过多年寻找解决方案,我来到这里,使用简单的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);
}
}

