Java 太多的样板文件,我如何减少我的POJO构建器?

Java 太多的样板文件,我如何减少我的POJO构建器?,java,android,design-patterns,builder,pojo,Java,Android,Design Patterns,Builder,Pojo,我有几种不同的方法使用a,但在为每种方法添加一个生成器并生成对象.toString、对象.hashCode和对象.equals之后,我的类最终大约有100行代码。必须有更好的方法来处理这个问题。我认为有一个反思性的建设者会有很大的帮助,但我不确定这是否是一个好的实践,我也不确定如何才能真正做到这一点。换句话说,有没有办法实现这样的构建器 一个简单的POJO: public class Foo { public int id; public String title; p

我有几种不同的方法使用a,但在为每种方法添加一个生成器并生成
对象.toString
对象.hashCode
对象.equals
之后,我的类最终大约有100行代码。必须有更好的方法来处理这个问题。我认为有一个反思性的建设者会有很大的帮助,但我不确定这是否是一个好的实践,我也不确定如何才能真正做到这一点。换句话说,有没有办法实现这样的构建器

一个简单的POJO:

public class Foo {

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

}
然后是某种反思性的建设者:

Foo = ReflectiveBuilder.from(Foo.class).id(1).title("title").change(false).build();
也许(是的,这个网站很难看)是你的选择。Lombok基于注释将代码注入到类中

使用Lombok,您可以使用
@Data
注释来生成getter、setter、
toString()
hashCode()
equals()

请查看上的示例以查看生成的代码

Lombok还提供了一个为类生成生成器的
@Builder
。但请注意,这是一个实验性特征:

@Builder
public class Foo {
    public int id;
    public String title;
    public boolean change;
}
现在您可以执行以下操作:

Foo foo = Foo.builder()
  .id(123)
  .title("some title")
  .change(true)
  .build();

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

你可以做的是:

Foo foo = ReflectiveBuilder.from(Foo.class).
              set("id", 1).
              set("title", "title").
              build();
这有三个巨大的问题:

  • 字段是
    String
    s-键入错误会导致运行时错误,而不是编译时错误
  • 值为
    Object
    s-错误的类型会导致运行时错误,而不是编译时错误,并且
  • 因为反射非常慢,所以它将比备选方案慢得多
  • 因此,一个基于反射的解决方案虽然可能(参见ApacheCommonsBeanutils),但并不实用

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

    真正神奇的是,所有的IDE,至少是大3,都理解注释预处理和代码完成,即使代码并不存在,也能正常工作

    在使用
    Builder
    POJO
    情况下,您可以使用和

    @Data
    注释将生成:

    • 必需的参数构造函数(接受所有
      final
      字段)
    • 等于使用所有字段的
      hashCode
      方法(可以使用注释进行配置)
    • 所有字段上的
      toString
      方法(可以配置注释和
    • public
      所有字段的getter和setter(可以使用字段上的注释进行配置)
    @Builder
    注释将生成一个名为
    Builder
    的内部类,该类可以使用
    Foo.Builder()
    进行实例化

    请确保将
    equals
    hashCode
    toString
    方法配置为两个Lombok类相互引用,然后在默认情况下,由于这两个类在这些方法中都包含另一个类,因此最终会出现无限循环

    还有一个新功能允许您使用,例如,fluent setters,这样,如果POJO是可变的,您就可以少做多做少做少:

    new Foo().setId(3).setTitle("title)...
    
    对于另一种方法,您可以查看(AOP)和.AOP,它允许您将类拆分为“方面”然后使用预编译器使用特定的规则将它们粘在一起。例如,您可以使用自定义注释和方面来实现Lombok所做的事情。然而,这是一个相当高级的主题,可能有点过头了。

    我创建了一个小库来流畅地初始化POJO。它使用反射,这当然是非常有用的不是很快。但是在需要编写测试时会非常有帮助

    Person person = CakeMold.of(Person.class)
        .set("firstName", "Bob")
        .set("lastName", "SquarePants")
        .set("email", "sponge.bob@bikinibottom.io")
        .set("age", 22)
        .cook();
    
    我个人使用网站为我创建POJO的所有样板代码。你所需要做的就是粘贴你想要解析的JSON,它将为你生成所有类。然后我只使用Reformation对信息进行请求/缓存/解析。这是我Github帐户中的Reformation和POJO示例。
    我希望这会有帮助!

    您是否使用Apache commons来编写toString hashCode和equals?这仍然是一件痛苦的事情,但会为您节省很多时间。您的代码有一个基类,它可以反射地编写toString、equals和hashCode,然后从中派生所有POJOthat@Leon事实上,我是这样做的。但是每个类最终还是会有70-100行来自每个构建的代码r、 必须有一种更好的模式,我只是不知道,或者有一种实现反射生成器的方法,至少我是这样认为的。我意识到,
    Gson
    实际上使用了一种非常类似的方法来反序列化
    对象
    ,因为它使用反射来初始化每个
    字段
    。基于相同反射的生成器校正可能不是一个坏主意。你认为呢?@buildpattern正如我所指出的,这是一个糟糕的想法。GSON这样做是因为它必须这样做。你失去了编译时类型安全性,这意味着你可以在任何时候遇到运行时错误,并且你会失去速度。除非你绝对必须,否则不要使用反射,永远不要减少样板。
    new Foo().setId(3).setTitle("title)...
    
    Person person = CakeMold.of(Person.class)
        .set("firstName", "Bob")
        .set("lastName", "SquarePants")
        .set("email", "sponge.bob@bikinibottom.io")
        .set("age", 22)
        .cook();