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 BeanUtilsBean
of the org.commons.beanutils
package? Actually, BeanUtils
uses 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 copyProperty
method, 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 NullAwareBeanUtilsBean
and 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 parent
is null, by simply copying it you have null also in anotherParent
right?
但是为什么你只想复制非空属性?如果一个属性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);
}
}