我有一个名为"XYZClientWrapper"的类,其结构如下:
@Builder
XYZClientWrapper{
String name;
String domain;
XYZClient client;
}
我希望不生成属性 XYZClient client
的构建函数。
Lombok支持这种用例吗?
另外,我发现将字段标记为final、static或static final会指示@Builder
忽略此字段。
@Builder
public class MyClass {
private String myField;
private final String excludeThisField = "bar";
}
Lombok 1.16.10
@Builder
只会添加没有值的final字段:final String myField
- 存在, final String myField=""
- 被忽略。 :) - Cherry@Builder
XYZClientWrapper{
String name;
String domain;
XYZClient client;
public static class XYZClientWrapperBuilder {
private XYZClientWrapperBuilder client(XYZClient client) { return this; }
}
}
client
参数会被忽略。 - Abhijit Sarkarprivate void client() {}
一起使用。 - Davidclient
,并且它可以依赖于先前由构建器设置的其他字段。XYZClientWrapper{
private final String name;
private final String domain;
private final XYZClient client;
@Builder
public XYZClientWrapper(String name, String domain) {
this.name = name;
this.domain = domain;
this.client = calculateClient();
}
}
针对工厂静态方法的示例:
class Car {
private String name;
private String model;
private Engine engine; // we want to ignore setting this
@Builder
private static Car of(String name, String model){
Car car=new Car();
car.name = name;
car.model = model;
constructEngine(car); // some static private method to construct engine internally
return car;
}
private static void constructEngine(Car car) {
// car.engine = blabla...
// construct engine internally
}
}
Car toyotaCorollaCar=Car.builder().name("Toyota").model("Corolla").build();
// You can see now that Car.builder().engine() is not available
of
将在调用build()时被调用,因此执行Car.builder().name("Toyota")
这样的操作并不会将值"Toyota"
设置到name
中,除非调用了build()
,然后在构造函数的静态方法of
内执行赋值逻辑。of
方法是私有访问的,以便build
方法是唯一对调用方可见的方法。@Builder
类中添加一个所谓的“partial builder”可以帮助解决问题。诀窍是像这样添加一个内部的局部构建器类:@Getter
@Builder
class Human {
private final String name;
private final String surname;
private final Gender gender;
private final String prefix; // Should be hidden, depends on gender
// Partial builder to manage dependent fields, and hidden fields
public static class HumanBuilder {
public HumanBuilder gender(final Gender gender) {
this.gender = gender;
if (Gender.MALE == gender) {
this.prefix = "Mr.";
} else if (Gender.FEMALE == gender) {
this.prefix = "Ms.";
} else {
this.prefix = "";
}
return this;
}
// This method hides the field from external set
private HumanBuilder prefix(final String prefix) {
return this;
}
}
}
PS:@Builder允许更改生成的构建器类名称。上面的示例假定使用默认的构建器类名称。
我发现我可以实现静态Builder类的"外壳",使用私有访问修饰符添加我想要隐藏的方法,并且它在构建器中不再可用。同样,我也可以向构建器添加自定义方法。
package com.something;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import java.time.ZonedDateTime;
@Data
@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MyClass{
//The builder will generate a method for this property for us.
private String anotherProperty;
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "localDateTime", column = @Column(name = "some_date_local_date_time")),
@AttributeOverride(name = "zoneId", column = @Column(name = "some__date_zone_id"))
})
@Getter(AccessLevel.PRIVATE)
@Setter(AccessLevel.PRIVATE)
private ZonedDateTimeEmbeddable someDateInternal;
public ZonedDateTime getSomeDate() {
return someDateInternal.toZonedDateTime();
}
public void setSomeDate(ZonedDateTime someDate) {
someDateInternal = new ZonedDateTimeEmbeddable(someDate);
}
public static class MyClassBuilder {
//Prevent direct access to the internal private field by pre-creating builder method with private access.
private MyClassBuilder shipmentDateInternal(ZonedDateTimeEmbeddable zonedDateTimeEmbeddable) {
return this;
}
//Add a builder method because we don't have a field for this Type
public MyClassBuilder someDate(ZonedDateTime someDate) {
someDateInternal = new ZonedDateTimeEmbeddable(someDate);
return this;
}
}
}
@Builder
public class Example {
private String field1;
private String field2;
private final AtomicReference<String> excluded = new AtomicReference<>(null);
}
excluded.set("Some value");
excluded.get();
@Builder
public class User{
@ToString.Exclude
private String passwordHash;
// ... rest of the properties
public static class UserBuilder {
private UserBuilder passwordHash(final String passwordHash){
return this;
}
}
}
class A {
private int required1;
private int required2;
private int optional1;
private int optional2;
public A(int required1, int required2) {
this.required1 = required1;
this.required2 = required2;
}
@Builder(toBuilder = true)
public A setOptionals(int optional1, int optional2) {
this.optional1 = optional1;
this.optional2 = optional2;
return this;
}
}
然后用以下方式构建
A a = new A(1, 2).builder().optional1(3).optional2(4).build();
这种方法的好处是可选项也可以有默认值。
@Builder
注释中添加类似于“_ignore_”属性或将注释@Builder.Ignore
添加到字段中? - pirho