Java 如何在 Lombok 中调用超级构造函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29740078/
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-11 08:32:01  来源:igfitidea点击:

how to Call super constructor in Lombok

javalombok

提问by user2067797

I have a class

我有一堂课

@Value
@NonFinal
public class A {
    int x;
    int y;
}

I have another class B

我还有一个B班

@Value
public class B extends A {
    int z;
}

lombok is throwing error saying it cant find A() constructor, explicitly call it what i want lombok to do is to give annotation to class b such that it generates the following code:

lombok 抛出错误,说它找不到 A() 构造函数,显式调用它我希望 lombok 做的是给 b 类注释,以便它生成以下代码:

public class B extends A {
    int z;
    public B( int x, int y, int z) {
        super( x , y );
        this.z = z;
    }
}

Do we have an annotation to do that in Lombok?

我们在龙目岛有注释可以做到这一点吗?

回答by Roel Spilker

This is not possible in Lombok. Although it would be a really nice feature, it requires resolution to find the constructors of the super class. The super class is only known by name the moment Lombok gets invoked. Using the import statements and the classpath to find the actual class is not trivial. And during compilation you cannot just use reflection to get a list of constructors.

这在龙目岛是不可能的。尽管这将是一个非常好的功能,但它需要解析才能找到超类的构造函数。只有在调用 Lombok 时才知道超类的名称。使用导入语句和类路径来查找实际类并非易事。在编译期间,您不能仅使用反射来获取构造函数列表。

It is not entirely impossible but the results using resolution in valand @ExtensionMethodhave taught us that is it hard and error-prone.

这不是完全不可能,但使用的分辨率结果val@ExtensionMethod教导我们是很难,而且容易出错。

Disclosure: I am a Lombok developer.

披露:我是龙目岛的开发人员。

回答by JJ Zabkar

Lombok Issue #78references this page https://www.donneo.de/2015/09/16/lomboks-builder-annotation-and-inheritance/with this lovely explanation:

Lombok Issue #78引用此页面https://www.donneo.de/2015/09/16/lomboks-builder-annotation-and-inheritance/并附有这个可爱的解释:

@AllArgsConstructor 
public class Parent {   
     private String a; 
}

public class Child extends Parent {
  private String b;

  @Builder
  public Child(String a, String b){
    super(a);
    this.b = b;   
  } 
} 

As a result you can then use the generated builder like this:

Child.builder().a("testA").b("testB").build(); 

The official documentationexplains this, but it doesn't explicitly point out that you can facilitate it in this way.

@AllArgsConstructor 
public class Parent {   
     private String a; 
}

public class Child extends Parent {
  private String b;

  @Builder
  public Child(String a, String b){
    super(a);
    this.b = b;   
  } 
} 

因此,您可以像这样使用生成的构建器:

Child.builder().a("testA").b("testB").build(); 

官方文件解释了这一点,但它并没有明确指出的是,你可以方便它以这种方式。

I also found this works nicely with Spring Data JPA.

我还发现这与 Spring Data JPA 配合得很好。

回答by Arne Burmeister

Lombok does not support that also indicated by making any @Valueannotated class final(as you know by using @NonFinal).

Lombok 不支持通过制作任何带@Value注释的类final(如您所知,使用@NonFinal)来表示。

The only workaround I found is to declare all members final yourself and use the @Dataannotation instead. Those subclasses need to be annotated by @EqualsAndHashCodeand need an explicit all args constructor as Lombok doesn't know how to create one using the all args one of the super class:

我发现的唯一解决方法是自己声明所有成员最终并使用@Data注释。这些子类需要被注释@EqualsAndHashCode并需要一个显式的 all args 构造函数,因为 Lombok 不知道如何使用超类的 all args 之一创建一个:

@Data
public class A {
    private final int x;
    private final int y;
}

@Data
@EqualsAndHashCode(callSuper = true)
public class B extends A {
    private final int z;

    public B(int x, int y, int z) {
        super(x, y);
        this.z = z;
    }
}

Especially the constructors of the subclasses make the solution a little untidy for superclasses with many members, sorry.

尤其是子类的构造函数,对于成员众多的超类来说,解决方案显得有些凌乱,抱歉。

回答by Kris

for superclasses with many members I would suggest you to use @Delegate

对于具有许多成员的超类,我建议您使用 @Delegate

@Data
public class A {
    @Delegate public class AInner{
        private final int x;
        private final int y;
    }
}

@Data
@EqualsAndHashCode(callSuper = true)
public class B extends A {
    private final int z;

    public B(A.AInner a, int z) {
        super(a);
        this.z = z;
    }
}

回答by Grigory Kislin

If child class has more members, than parent, it could be done not very clean, but short way:

如果子类的成员多于父类,则可以做得不是很干净,但方法很短:

@Data
@RequiredArgsConstructor
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class User extends BaseEntity {
    private @NonNull String fullName;
    private @NonNull String email;
    ... 

    public User(Integer id, String fullName, String email, ....) {
        this(fullName, email, ....);
        this.id = id;
    }
}

@Data
@AllArgsConstructor
abstract public class BaseEntity {
   protected Integer id;

   public boolean isNew() {
      return id == null;
   }
}

回答by Alan Ho

Version 1.18 of Lombok introduced the @SuperBuilder annotation. We can use this to solve our problem in a simpler way.

Lombok 1.18 版引入了@SuperBuilder 注释。我们可以使用它以更简单的方式解决我们的问题。

You can refer to https://www.baeldung.com/lombok-builder-inheritance#lombok-builder-and-inheritance-3.

您可以参考https://www.baeldung.com/lombok-builder-inheritance#lombok-builder-and-inheritance-3

so in your child class, you will need these annotations:

因此,在您的子类中,您将需要这些注释:

@Data
@SuperBuilder
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)

in your parent class:

在您的父类中:

@Data
@SuperBuilder
@NoArgsConstructor