我有一个简单的Java POJO,我会将属性复制到同一个POJO类的另一个实例。
我知道我可以使用BeanUtils.copyProperties()来做到这一点,但我想避免使用第三方库。
那么,如何以简单,恰当和安全的方式做到这一点?
顺便说一下,我正在使用Java 6.
答案 0 :(得分:12)
我想如果你看一下BeanUtils的源代码,它会告诉你如何在不使用BeanUtils的情况下做到这一点。
如果您只是想创建POJO的副本(与将属性从一个POJO复制到另一个POJO不完全相同),您可以更改源bean以实现clone()方法和Cloneable接口。 / p>
答案 1 :(得分:11)
我在为Google App Engine开发应用时遇到了同样的问题,由于公共日志限制,我无法使用BeanUtils。无论如何,我提出了这个解决方案并且对我来说工作得很好。
public static void copyProperties(Object fromObj, Object toObj) {
Class<? extends Object> fromClass = fromObj.getClass();
Class<? extends Object> toClass = toObj.getClass();
try {
BeanInfo fromBean = Introspector.getBeanInfo(fromClass);
BeanInfo toBean = Introspector.getBeanInfo(toClass);
PropertyDescriptor[] toPd = toBean.getPropertyDescriptors();
List<PropertyDescriptor> fromPd = Arrays.asList(fromBean
.getPropertyDescriptors());
for (PropertyDescriptor propertyDescriptor : toPd) {
propertyDescriptor.getDisplayName();
PropertyDescriptor pd = fromPd.get(fromPd
.indexOf(propertyDescriptor));
if (pd.getDisplayName().equals(
propertyDescriptor.getDisplayName())
&& !pd.getDisplayName().equals("class")) {
if(propertyDescriptor.getWriteMethod() != null)
propertyDescriptor.getWriteMethod().invoke(toObj, pd.getReadMethod().invoke(fromObj, null));
}
}
} catch (IntrospectionException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
非常欢迎任何增强或推荐。
答案 2 :(得分:3)
另一个替代方法是MapStruct,它在构建时生成映射代码,从而产生类型安全的映射,在运行时不需要任何依赖(免责声明:我是MapStruct的作者)。
答案 3 :(得分:3)
嘿朋友们只需使用我创建的ReflectionUtil类将一个bean值复制到另一个类似的bean。
该类还将复制Collections对象。
https://github.com/vijayshegokar/Java/blob/master/Utility/src/common/util/reflection/ReflectionUtil.java
注意:此bean必须具有类似的变量名称,并且具有getter和setter。
现在增加了更多功能。您还可以将一个实体数据复制到其bean。 如果一个实体中有另一个实体,那么您可以将内部实体的运行时更改的map选项传递给其相关的bean。
例如
ParentEntity parentEntityObject = getParentDataFromDB();
Map<Class<?>, Class<?>> map = new HashMap<Class<?>, Class<?>>();
map.put(InnerBean1.class, InnerEntity1.class);
map.put(InnerBean2.class, InnerEntity2.class);
ParentBean parent = ReflectionUtil.copy(ParentBean.class, parentEntityObject, map);
当您的实体包含关系时,此案例非常有用。
答案 4 :(得分:2)
查看JavaBeans API,特别是Introspector课程。您可以将BeanInfo元数据用于get和set属性。如果你还没有阅读JavaBeans specification,最好先阅读。它也有助于熟悉reflection API。
答案 5 :(得分:1)
没有简单的方法可以做到。 Introspector和Java bean库是单片的 - BeanUtils是一个简单的包装器并且运行良好。没有库只是为了没有库通常是一个坏主意 - 这是一个共同的原因 - Java应该存在的常见功能,但不是。
答案 6 :(得分:1)
我遇到了Introspector.getBeanInfo
没有返回所有属性的问题,所以我最终实现了字段副本而不是属性副本。
public static <T> void copyFields(T target, T source) throws Exception{
Class<?> clazz = source.getClass();
for (Field field : clazz.getFields()) {
Object value = field.get(source);
field.set(target, value);
}
}
答案 7 :(得分:0)
您可以使用 Java Reflection API 来实现它。
public static <T> void copy(T target, T source) throws Exception {
Class<?> clazz = source.getClass();
for (Field field : clazz.getDeclaredFields()) {
if (Modifier.isPrivate(field.getModifiers()))
field.setAccessible(true);
Object value = field.get(source);
field.set(target, value);
}
}