【问题标题】:How can I avoid so many if statements in copying one object to another?在将一个对象复制到另一个对象时,如何避免使用这么多 if 语句?
【发布时间】:2020-05-16 08:38:13
【问题描述】:

我有以下课程:

public class File
{
@Getter
@Setter
private String id;

@Getter
@Setter
private String name;

@Getter 
@Setter
private int size;

@Getter
@Setter
private String color;

... about 10 more variables
}

我有这个类的两个实例:

File file = new File(); // assume each variable has a value initialized
File newFile = new File(); // assume each variable has a value initialized

我想要的逻辑是如果我的newFile 包含一个变量的值,我想保留它。否则,我想回退到 file 对象中的原始值。

所以我有以下方法:

public void merge(File oldFile, File newFile)
{
    if (newFile.getId() != null)
    {
       oldFile.setId(newFile.getId());
    }

    if (newFile.getName() != null)
    {
       oldFile.setName(newFile.getName());
    }

    if (newFile.getSize() != null)
    {
       oldFile.setSize(newFile.getSize());
    }

    if (newFile.getColor() != null)
    {
       oldFile.setColor(newFile.getColor());
    }

    ... etc
}

如何避免如此多的 if 语句和空检查?在我看来,代码看起来很丑。

【问题讨论】:

  • 为什么需要空检查?如果允许空值,只需复制空值。
  • 如果它为 null,则意味着我想回退到 oldFile 值是什么,我不想用 null 替换它。请参阅我的评论“我想要的逻辑是,如果我的 newFile 包含变量的值,我想保留它。否则我想回退到文件对象中的原始值。”
  • 你用龙目岛吗?
  • @sc0der 是的,我也在研究一个名为 ModelMapper 的库,我想知道这在这里是否有用。
  • 这能回答你的问题吗? Copy POJO content from one bean to another

标签: java


【解决方案1】:

如果新值为 null,您可以编写一个默认为旧值的函数 - 或者您可以使用预先编写的函数,例如: https://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/ObjectUtils.html#defaultIfNull(T,%20T)

这意味着你的代码变成了:

public void merge(File oldFile, File newFile)
{
   oldFile.setId(defaultIfNull(newFile.getId(), oldFile.getId());

   oldFile.setName(defaultIfNull(newFile.getName(), oldFile.getName());

   oldFile.setSize(defaultIfNull(newFile.getSize(), oldFile.getSize());

   // etc

}

当然,如果您决定这种行为应该始终适用于您的文件,那么您可以将其放入所有设置器中,例如:

public void setName(String name) {
    this.name = defaultIfNull(name, this.name);
}

然后正常调用:

public void merge(File oldFile, File newFile)
{
   oldFile.setId(newFile.getId());

   oldFile.setName(newFile.getName());

    // etc
}

【讨论】:

  • defaultIfNull 还不错...我只是认为回退并调用具有相同值的 setter 有点奇怪,它已经设置为好像新值为 null,我认为最好不要甚至调用 setter
  • 取决于您如何定义“怪异”和“更好”:)。恕我直言,我认为我提到的两种形式都比问题中缩进的 if 块“更好”,而且这两种形式也是我在工作中看到的常见做法。
【解决方案2】:

您可以在 Utility 类中创建 merge 函数,该函数接受两个文件对象并使用反射来执行此操作

    static final class FileUtil {

        private FileUtil() throws IllegalAccessException {
            throw new IllegalAccessException("can not create an object from this class!");
        }

        public final static void merge(File oldFile, File newFile) throws Exception {
            Method[] methods = newFile.getClass().getDeclaredMethods();
            for (Method m : methods) {
                if (m.getName().contains("get")) {
                    Object value = m.invoke(newFile);
                    if (value != null) {
                        String name = m.getName();
                        name = name.substring(name.indexOf("get") + 3);
                        name = "set" + name;
                        if (value instanceof Integer) {
                            Method method = oldFile.getClass().getDeclaredMethod(name, int.class);
                            method.invoke(oldFile, (int) value);
                        } else {
                            Method method = oldFile.getClass().getDeclaredMethod(name, value.getClass());
                            method.invoke(oldFile, value);
                        }
                    }
                }
            }
        }
    }

【讨论】:

    猜你喜欢
    • 2013-10-08
    • 1970-01-01
    • 2012-05-15
    • 2011-02-07
    • 2017-01-23
    • 1970-01-01
    • 2020-01-02
    • 1970-01-01
    相关资源
    最近更新 更多