太多的样板,我怎样才能减少我的POJO建造者?

bui*_*ern 6 java android design-patterns builder pojo

我有几个不同的POJO使用一个生成器模式,但添加的助洗剂为每一个和生成后Object.toString,Object.hashCodeObject.equals,我的类最终会被大约100行代码.必须有一个更好的方法来处理这个问题.我认为拥有一些反思性的建设者会有很多帮助,但我不确定这是不是很好的做法,而且我也不确定我是如何做到这一点的.换句话说,有没有办法实现这样的构建器?

一个简单的POJO:

public class Foo {

    public int id;
    public String title;
    public boolean change;
    ...

}
Run Code Online (Sandbox Code Playgroud)

然后某种反思建设者:

Foo = ReflectiveBuilder.from(Foo.class).id(1).title("title").change(false).build();
Run Code Online (Sandbox Code Playgroud)

Bor*_*der 4

简短的回答:。你所要求的是不可能的。反射在运行时查看代码并动态调用方法,它不能生成实际的方法。

你可以做的是:

Foo foo = ReflectiveBuilder.from(Foo.class).
              set("id", 1).
              set("title", "title").
              build();
Run Code Online (Sandbox Code Playgroud)

这存在三个问题:

  1. 这些字段是Strings - 拼写错误会导致运行时错误而不是编译时错误,
  2. 值是Objects - 错误的类型会导致运行时错误而不是编译时错误,并且
  3. 它会比替代方案慢得多,因为反射非常慢。

因此,基于反射的解决方案虽然可能(请参阅 Apache Commons BeanUtils BeanMap),但根本不实用。

长答案,如果您愿意允许一些编译时魔法,您可以使用Project Lombok。Lombok 背后的想法是使用 Java 注释预处理器系统从注释生成样板代码。

真正神奇的是,所有 IDE(至少是三大 IDE)都了解注释预处理和代码完成,即使代码并不真正存在,仍然可以正确运行。

POJO在 a与 a的情况下,Builder您可以使用@Dataand@Builder

@Data
@Builder
public class Foo {

    public int id;
    public String title;
    public boolean change;
    ...

}
Run Code Online (Sandbox Code Playgroud)

@Data注释将生成:

  • 一个必需的参数构造函数(接受所有final字段),
  • equals以及hashCode使用所有字段的方法(可以通过@EqualsAndHashCode注解进行配置)
  • 所有字段上的方法toString(可以使用@ToString注释进行配置)
  • public所有字段的 getter 和 setter(可以使用字段上的@Getter/@Setter注释进行配置)。

@Builder注释将生成一个名为 的内部类Builder,可以使用 实例化该内部类Foo.builder()

请确保您配置equals,hashCodetoString方法,就好像您有两个带有 Lombok 的类,它们相互引用,那么在默认情况下您将最终陷入无限循环,因为这两个类在这些方法中都包含另一个类。

还有一个新的配置系统,允许您使用例如流利的设置器,这样如果您的 POJO 是可变的,您就可以或多或少地取消构建器:

new Foo().setId(3).setTitle("title)...
Run Code Online (Sandbox Code Playgroud)

对于另一种方法,您可以查看面向方面的编程(AOP)和AspectJ。AOP 允许您将类分成“方面”,然后使用预编译器使用某些规则将它们粘在一起。例如,您可以使用自定义注释和方面来准确实现 Lombok 的功能。然而,这是一个相当高级的主题,而且很可能有点矫枉过正。