有没有更好的方法可以在不使用反射的情况下从对象克隆值?

时间:2018-11-14 02:33:49

标签: java java-8

尝试有效地检查对象的新副本是否具有任何不同的字段,如果有,则更新本地字段并记下该字段。如果任何字段更改,则需要将对象持久保存到数据库。如果不想,我不想打那个电话,因此是布尔值。

我想不出一个更好的方法而不使用反射,但是我不想在这里使用反射,因为缺乏编译器支持的安全性(将有对字段名称的字符串引用),而没有所有字段都是同一类型(我那里有一些Java 8 Instant字段)。

我真正要避免的是记账,当字段被修改时,必须记住要向sync方法添加或减去。显然,减法没什么大不了的,因为该方法会中断,但是如果有人不记得要更新新字段,那么加法就很可怕了。

public boolean syncWithFieldsFrom(User currentUser) {
    boolean doesUserNeedUpdating = false;
    if (!StringUtils.equals(email, currentUser.email)) {
        email = currentUser.email;
        doesUserNeedUpdating = true;
    }
    if (!StringUtils.equals(firstName, currentUser.firstName)) {
        firstName = currentUser.firstName;
        doesUserNeedUpdating = true;
    }
    if (!StringUtils.equals(lastName, currentUser.lastName)) {
        lastName = currentUser.lastName;
        doesUserNeedUpdating = true;
    }
    if (!StringUtils.equals(fullName, currentUser.fullName)) {
        fullName = currentUser.fullName;
        doesUserNeedUpdating = true;
    }
    return doesUserNeedUpdating;
}

2 个答案:

答案 0 :(得分:7)

这可能有点矫kill过正,但是您可以使用lambda提取字段并针对它们运行循环。为了简单起见,我假设您有getter和setter。

private static class Field<T> {
    final Function<User, T> getter;
    final BiConsumer<User, T> setter;

    Field(Function<User, T> getter, BiConsumer<User, T> setter) {
        this.getter = getter;
        this.setter = setter;
    }

    boolean sync(User src, User dst) {
        T srcField = getter.apply(src);
        if (!Objects.equal(srcField, getter.apply(dst))) {
            setter.accept(dst, srcField);
            return true;
        }
        return false;
    }
}

private static final List<Field<?>> FIELDS = Arrays.asList(
        new Field<>(User::getEmail, User::setEmail),
        new Field<>(User::getFirstName, User::setFirstName),
        new Field<>(User::getLastName, User::setLastName),
        new Field<>(User::getFullName, User::setFullName));

public boolean syncWithFieldsFrom(User currentUser) {
    boolean updated = false;
    for (Field<?> f : FIELDS) {
        updated |= f.sync(currentUser, this);
    }
    return updated;
}

答案 1 :(得分:0)

用于深度克隆(克隆整个对象层次结构):     commons-lang SerializationUtils-使用序列化-如果所有类都在     控制,您可以强制实施Serializable。

Java Deep Cloning Library - using reflection - in cases when the classes or the 
objects you want to clone are out of your control (a 3rd party library) and you can't 
make them implement Serializable, or in cases you don't want to implement Serializable.

用于浅克隆(仅克隆第一级属性):      commons-beanutils BeanUtils-在大多数情况下。

 Spring BeanUtils - if you are already using spring and hence have this utility on 
 the classpath.

 I deliberately omitted the "do-it-yourself" option - the API's above provide a good 
 control over what to and what not to clone (for example using transient, or String[] 
 ignoreProperties), so reinventing the wheel isn't preferred.

请参考以下网址。可能会帮助您了解一些想法。

Java: recommended solution for deep cloning/copying an instance