簡體   English   中英

如何將屬性從一個Java bean復制到另一個?

[英]How to copy properties from one Java bean to another?

我有一個簡單的Java POJO,我將屬性復制到同一個POJO類的另一個實例。

我知道我可以用BeanUtils.copyProperties()做到這一點,但我想避免使用第三方庫。

那么,如何簡單地,正確和安全的方式呢?

順便說一下,我正在使用Java 6。

我想如果你看一下BeanUtils的源代碼,它會告訴你如何在不使用BeanUtils的情況下做到這一點。

如果您只是想創建POJO的副本(與將屬性從一個POJO復制到另一個POJO不完全相同),您可以更改源bean以實現clone()方法和Cloneable接口。

在為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();
    }
}

任何增強或推薦都非常受歡迎。

另一種選擇是MapStruct ,它在構建時生成映射代碼,從而產生類型安全的映射,在運行時不需要任何依賴(免責聲明:我是MapStruct的作者)。

嘿朋友們只是使用我創建的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);

當您的實體包含關系時,此案例非常有用。

查看JavaBeans API ,特別是Introspector類。 您可以使用BeanInfo元數據來獲取設置屬性。 如果您還沒有閱讀JavaBeans規范,那么這是一個好主意。 它也有助於熟悉反射API

沒有簡單的方法來做到這一點。 Introspector和Java bean庫是單片的 - BeanUtils是一個簡單的包裝器並且運行良好。 沒有庫只是沒有庫通常是一個壞主意 - 有一個原因是它的開頭 - Java應該存在的常見功能,但不是。

我遇到了一些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);
    }
}

您可以使用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);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM