如何在龙目岛中调用超级构造函数


118

我有一堂课

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

我还有另一个B班

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

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;
    }
}

在龙目岛中是否有注释可以做到这一点?

Answers:


169

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

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

披露:我是Lombok开发人员。


@ roel-spilker我们了解其背后的复杂性。但是Lombok是否可以提供一种inConstructor用于构造函数批注的方法,在这里我们可以指定superLombok应该将哪个构造函数注入到生成的构造函数中?
Manu Manjunath

1
afterConstructor也会很好地执行一些自动初始化
Pawel

@ Manu / @ Pawel:请参阅lombok增强请求:github.com/peichhorn/lombok-pg/issues/78 (当前打开)
JJ Zabkar

由于@Builder正式发布,请参见:github.com/rzwitserloot/lombok/issues/853
塞巴斯蒂安

4
还是不可能?
FearX

21

龙目岛第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;   
  } 
} 

因此,您可以使用生成的生成器,如下所示:

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

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

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


您能否提供一个与Spring Data JPA一起使用的示例?
Marc Zampetti

29
这根本无法回答问题。相反,它是手工完成的,而问题是如何生成它。同时,通过拖动@Builder会使整个事情更加混乱,这与问题没有任何关系。
贾斯珀(Jasper)

8
实际上,这对于只想创建继承结构然后使用生成器的人来说非常有用。这是我仍然使用#lombok的99%原因。有时我们只需要手工制作东西即可使其按我们期望的方式工作。所以感谢@ jj-zabkar
亲王

但是之后; 只需编写self + parent arg构造函数的代码即可。无需使用生成器
Juh_

它可以在STS和Eclipse中使用,但是当您生成应用程序的JAR文件时,很可能会失败。我尝试了两个SuperBuilder,Builder进行继承。都失败了。小心 !!
P Satish Patro

6

Lombok不支持通过创建任何带@Value注释的类final(通过使用来知道@NonFinal)来表明这一点。

我发现的唯一解决方法是将所有成员声明为final并使用@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;
    }
}

遗憾的是,尤其是子类的构造函数使解决方案对于具有许多成员的超类显得有些混乱。


1
您能否再解释一下为什么“子类需要用@EqualsAndHashCode” 来注释?这个注释不包括在内@Data吗?Thx :)
Gerard Bosch

1
@GerardB @Data还创建equals()和hashCode(),但不在乎任何继承。为确保使用超类equals()和hashCode(),您需要使用callSuper显式生成
Arne Burmeister

5

对于具有许多成员的超类,我建议您使用@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;
    }
}

喜欢这是一种有趣的方法!
Arne Burmeister

@Delegate@Target({ElementType.FIELD, ElementType.METHOD})AInner 应该在A
boriselec

3

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

@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;
   }
}


0

作为一种选择,您可以用来com.fasterxml.jackson.databind.ObjectMapper从父级初始化子级

public class A {
    int x;
    int y;
}

public class B extends A {
    int z;
}

ObjectMapper MAPPER = new ObjectMapper(); //it's configurable
MAPPER.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false );
MAPPER.configure( SerializationFeature.FAIL_ON_EMPTY_BEANS, false );

//Then wherever you need to initialize child from parent:
A parent = new A(x, y);
B child = MAPPER.convertValue( parent, B.class);
child.setZ(z);

lombok如果需要,您仍然可以在A和B上使用任何注释。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.