java中的空检查重构

java中的空检查重构,java,refactoring,Java,Refactoring,我们有两个班: class Foo { private String a; private String b; private String c; ... getter...setter... } class Boo { private String a; private String b; private String c; ... getter...setter... } 假设Foo和Bar不同,但某些字段相

我们有两个班:

class Foo {
    private String a;
    private String b;
    private String c;
    ...
    getter...setter...
}

class Boo {
    private String a;
    private String b;
    private String c;
    ...
    getter...setter...
}
假设Foo和Bar不同,但某些字段相同

下面是我要执行的代码:

  private void map(foo f) {
    Boo b = new Boo();
    if (f.getA() != null)  b.setA(f.getA());
    if (f.getB() != null)  b.setB(f.getB());
    if (f.getC() != null)  b.setC(f.getC());
    ....
  }
3个字段不是什么大问题

但是如果有很多字段,那么也会有很多if()


我想知道在java或C++中有一个很好的自动和程序好方法。

也许你应该把你的字符串存储在一个地图中。< /P> 当您填充foo类时,可以使用insert进行填充


然后,当您想要相互复制时,您可以迭代这些值。

也许您应该将字符串存储在映射中

当您填充foo类时,可以使用insert进行填充


然后,当您想要相互复制时,可以迭代这些值。

如果类中有很多成员,可以使用反射来复制字段。这将允许您也正确复制
null
值。它有很多更脆弱的代码,因此只有当您有很多成员时,它才会有用。

如果类中有很多成员,您可以使用反射来复制字段。这将允许您也正确复制
null
值。它有很多更脆弱的代码,因此只有当您有很多成员时,它才会有用。

std::optional

在C++17中,这是超级自动化的(在C++17之前,您只需获取
可选
类的任何实现,并让代码以相同的方式工作)

类容器{
公众:
std::数组三个字符串为空;
};
int main(){
自动字符串=std::array{};
//填充字符串或不填充字符串
自动容器=容器{};
container.three_string_nullables=字符串;
}

P> >泛化这个选项,您可以考虑将opopes放在一个动态大小的容器中,比如<代码> STD::vector < /代码>

< P> < >代码> STD::可选的<代码> <强> >p> 在C++17中,这是超级自动化的(在C++17之前,您只需获取
可选
类的任何实现,并让代码以相同的方式工作)

类容器{
公众:
std::数组三个字符串为空;
};
int main(){
自动字符串=std::array{};
//填充字符串或不填充字符串
自动容器=容器{};
container.three_string_nullables=字符串;
}

泛化这一点,可以考虑将opopes放入一个动态大小的容器中,比如<>代码>::vector > /p> < p>您可以使用java反射API来完成这个任务。反射允许您获取关于类的元数据(例如:类中的字段、方法和其他)。除此之外,您还可以调用类方法。您可以从类中获取所有setter和getter,并根据这些信息进行必要的调用。

您可以使用java反射API完成此任务。反射允许您获取关于类的元数据(例如:类中的字段、方法和其他)。除此之外,您还可以调用类方法。您可以从类中获取所有setter和getter,并根据这些信息进行必要的调用。

或者您可以使用类似于Dozer的映射框架:

您可以编写如下代码:

Mapper mapper = new DozerBeanMapper();
Boo destObject = new Boo();
mapper.map(foo, destObject);
。。。它会将属性从一个对象复制到另一个对象(使用反射)


通过额外的配置,您可以添加转换逻辑或非平凡的映射规则(获取Foo#prop1的值并将其置于Boo#prop2)或对象图的深度副本。还有更多。

或者您可以使用类似于Dozer的映射框架:

您可以编写如下代码:

Mapper mapper = new DozerBeanMapper();
Boo destObject = new Boo();
mapper.map(foo, destObject);
。。。它会将属性从一个对象复制到另一个对象(使用反射)

通过额外的配置,您可以添加转换逻辑或非平凡的映射规则(获取Foo#prop1的值并将其置于Boo#prop2)或对象图的深度副本。还有更多。

真正的答案是退后一步,看看驱动你的问题的需求

你看,好的OO是关于创建模型,也就是表示代码所处理的“真实世界元素”的抽象。以一种有帮助的方式。从这个意义上讲,好的OO更多的是关于行为(也称为方法)而不是关于状态(称为字段)

从这里开始:拥有拥有大量字段的类已经是第一个设计风格了。然后,在大多数/所有这些字段上使用getter/setter会让事情变得更糟

除此之外:当您有两个类A和B时。A有5个字段,B有7个字段。。。你会发现其中3个字段是“普通的”。。。真正的答案是:创建一个包含这3个字段的C类;然后将C类型的字段放入a和B中。是的,默认值是在a和B中有一个C字段,因为您需要

所以,是的;有一些框架可以帮助实现这一点。或者,您可以将字段重新组织到单个映射实例中

但是(可能是固执己见的):我认为你应该先和一些真实的人谈谈,回顾一下当前的解决方案,问问自己:“我们在这里做的是真正的OO吗;或者我们的对象只是我们移动的记录,然后程序代码正在处理的记录吗?”。换句话说,问问你自己你是否真的在做OOP。

真正的答案是退后一步,看看驱动你的问题的需求

你看,好的OO是关于创建模型,也就是表示代码所处理的“真实世界元素”的抽象。以一种有帮助的方式。从这个意义上讲,好的OO更多的是关于行为(也称为方法)而不是关于状态(称为字段)

从这里开始:拥有拥有大量字段的类已经是第一个设计风格了。然后,在大多数/所有这些字段上使用getter/setter会让事情变得更糟

除此之外:当您有两个类A和B时。A有5个字段,B有7个字段。。。你会发现其中的3个
static <X> void setIfNotNull(Consumer<X> setter, Supplier<X> getter) {
    X value = getter.get();
    if (value != null)
        setter.accept(value);
}

private void map(Foo f) {
    Boo b = new Boo();
    setIfNotNull(b::setA, f::getA);
    setIfNotNull(b::setB, f::getB);
    setIfNotNull(b::setC, f::getC);
}