Java Lombok @builder 在扩展另一个类的类上

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/44948858/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 01:48:55  来源:igfitidea点击:

Lombok @builder on a class that extends another class

javaspringhibernatelombok

提问by zur

I have two classes Childextends Parent. I need to put @Builder annotation on the classes such that I do not need to create the builder my self.

我有两个类Childextends Parent。我需要在类上添加 @Builder 注释,这样我就不需要自己创建构建器。

package jerry;// Internal compiler error: java.lang.NullPointerException

import lombok.AllArgsConstructor;
import lombok.Builder;

@AllArgsConstructor(onConstructor=@__(@Builder))
public class Child extends Parent { 
//Multiple markers at this line
//  - Implicit super constructor Parent() is undefined. Must explicitly invoke another constructor
//  - overrides java.lang.Object.toString

   private String a;
   private int b;
   private boolean c;

}


@Builder
public class Parent {
    private double d;
    private float e;
}

I need to be able to build child instance such that

我需要能够构建子实例,以便

Child child = Child.builder().a("aVal").b(1000).c(true).d(10.1).e(20.0F).build();

But so far I am getting the errors mentioned in side that code comments. Can any one point me to the right direction how to achieve it with lombok or any other similar library ?

但到目前为止,我收到了代码注释中提到的错误。任何人都可以指出我如何使用 lombok 或任何其他类似库实现它的正确方向吗?

Sub-question

子问题

Why does @AllArgsConstructor(onConstructor=@__(@Autowired))compile but @AllArgsConstructor(onConstructor=@__(@Builder))does not?

为什么@AllArgsConstructor(onConstructor=@__(@Autowired))编译但@AllArgsConstructor(onConstructor=@__(@Builder))不编译?

回答by hammerfest

See in https://blog.codecentric.de/en/2016/05/reducing-boilerplate-code-project-lombok/(@Builder and inheritancepart)

https://blog.codecentric.de/en/2016/05/reducing-boilerplate-code-project-lombok/@Builder和继承的部分)

Adjusted to your classes

根据您的课程进行调整

@AllArgsConstructor
public class Parent {
  private double d;
  private float e;
}

public class Child extends Parent {
  private String a;
  private int b;
  private boolean c;

  @Builder
  public Child(String a, int b, boolean c, double d, float e) {
    super(d, e);
    this.a = a;
    this.b = b;
    this.c = c;
  }
}

With this setup

有了这个设置

Child child = Child.builder().a("aVal").b(1000).c(true).d(10.1).e(20.0F).build();

works correctly

工作正常

回答by rsenden

I have a similar but slightly different use case. In my case, I have a chain of abstract super classes that build and execute requests. Different requests share some common parameters, but not every request supports all parameters. The builders for concrete requests should only provide methods for setting supported parameters for a given request.

我有一个类似但略有不同的用例。就我而言,我有一系列抽象超类来构建和执行请求。不同的请求共享一些通用参数,但并非每个请求都支持所有参数。具体请求的构建器应该只提供为给定请求设置支持参数的方法。

I started out with the constructor-based builder implementations, but this resulted in too much boilerplate code, especially if you have many fields to be configured. I have now come up with the following solutions, which looks much cleaner to me.

我从基于构造函数的构建器实现开始,但这导致了太多的样板代码,尤其是当您要配置许多字段时。我现在提出了以下解决方案,对我来说看起来更干净。

Basically the concrete subclasses define the actual fields that the Builder should support, and the Getter annotation results in the corresponding superclass methods to be overridden. The getters in the abstract superclasses can even be defined as abstract to require concrete implementations to define those fields.

基本上,具体的子类定义了 Builder 应该支持的实际字段,而 Getter 注释导致相应的超类方法被覆盖。抽象超类中的 getter 甚至可以定义为抽象,以需要具体的实现来定义这些字段。

public abstract class AbstractSuperClass1 {
    protected String getParamA() { return "defaultValueA"; }

    public final void doSomething() {
        System.out.println(getParamA());
        doSomeThingElse();
    }

    protected abstract void doSomeThingElse();
}


public abstract class AbstractSuperClass2 extends AbstractSuperClass1 {
    protected String getParamB() { return "defaultValueB"; }

    protected void doSomeThingElse() {
        System.out.println(getParamB());
    }
}


import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;

@Getter(AccessLevel.PROTECTED) @Builder
public class ConcreteClass1 extends AbstractSuperClass2 {
    private final String paramA;
    // Not supported by this implementation: private final String paramB;

    public static void main(String[] args) {
        ConcreteClass1.builder()
           .paramA("NonDefaultValueA")
           .build().doSomething();
    }
}


import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;

@Getter(AccessLevel.PROTECTED) @Builder
public class ConcreteClass2 extends AbstractSuperClass2 {
    private final String paramA;
    private final String paramB;

    public static void main(String[] args) {
        ConcreteClass2.builder()
            .paramA("NonDefaultValueA").paramB("NonDefaultValueB")
            .build().doSomething();
    }
}

回答by Jan Rieke

Since release 1.18.2 lombok includes the new experimental @SuperBuilder. It supports fields from superclasses (also abstract ones). With it, the solution is as simple as this:

自 1.18.2 版以来,lombok 包含新的实验性@SuperBuilder. 它支持来自超类(也是抽象类)的字段。有了它,解决方案就这么简单:

@SuperBuilder
public class Child extends Parent {
   private String a;
   private int b;
   private boolean c;
}

@SuperBuilder
public class Parent {
    private double d;
    private float e;
}

Child instance = Child.builder().b(7).e(6.3).build();

Update 2019-10-09:If you use IntelliJ, you need at least version 0.27 of the IntelliJ Lombok plugin to use @SuperBuilder.

2019-10-09 更新:如果你使用 IntelliJ,你需要至少 0.27 版的 IntelliJ Lombok 插件才能使用@SuperBuilder.

PS: @AllArgsConstructor(onConstructor=@__(@Builder))does not work because @Builderis an annotation-processing annotation that lombok translates to code during compilation. Generating and then translating new lombok annotation would require several iterations of annotation processing, and lombok does not support that. @Autowired, in contrast, is a regular Java annotation available at runtime.

PS:@AllArgsConstructor(onConstructor=@__(@Builder))不起作用,因为@Builder是 lombok 在编译期间转换为代码的注释处理注释。生成然后翻译新的 lombok 注释需要多次迭代注释处理,而 lombok 不支持。@Autowired相比之下,是运行时可用的常规 Java 注释。