web-dev-qa-db-ja.com

Lombokビルダーからプロパティを除外する方法は?

「XYZClientWrapper」というクラスがあり、次の構造があります。

@Builder
XYZClientWrapper{
    String name;
    String domain;
    XYZClient client;
}

プロパティXYZClient clientに対してビルド関数を生成しないこと

Lombokはそのようなユースケースをサポートしていますか?

35
Vivek Goel

はい。必要なフィールドのみを含むコンストラクタまたは静的(ファクトリ)メソッドに @ Builder を配置できます。

開示:私はロンボク島の開発者です。

79
Roel Spilker

あるいは、フィールドをfinalstaticまたはstatic finalとしてマークすると、@Builderこのフィールドを無視します。

@Builder
public class MyClass {
   private String myField;

   private final String excludeThisField = "bar";
}

ロンボク1.16.1

9
Stephan

静的な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;
        }
    }

}
5

コードでビルダーを作成し、プロパティのプライベートセッターを追加します。

@Builder
XYZClientWrapper{
    String name;
    String domain;
    XYZClient client;

    public static class XYZClientWrapperBuilder {
        private XYZClientWrapperBuilder client(XYZClient client) { return this; }
    }
}
4
Bill H

これが私の好ましい解決策です。これにより、フィールドclientを最後に作成し、ビルダーによって以前に設定された他のフィールドに依存させることができます。

XYZClientWrapper{
    String name;
    String domain;
    XYZClient client;

    @Builder
    public XYZClientWrapper(String name, String domain) {
        this.name=name;this.domain=domain;
        this.client=calculateClient();
    }
}
3
SexyNerd

工場出荷時の静的メソッドの例

Class Car{
   private String name;
   private String model;


   private Engine engine; // we want to ignore setting this

   @Builder
   public static Car of(String name, String model){
      Car car=new Car();
      car.setName(name);
      car.setModel(model);
      constructEngine(); // some private method to construct engine internally
      return car;  
   }

   private constructEngine(){// construct engine internally}
}

次のように使用できます:

main(String[] args){

   Car toyotaCorollaCar=Car.builder().name("Toyota").model("Corolla");
   // You can see now that Car.builder().engine() is not available

}

Build()が呼び出されるたびに静的メソッドofが呼び出されることに注意してください。そのため、Car.builder().name("Toyota")のようなものを実行しても、build()が呼び出されてからコンストラクターの静的メソッドnameが割り当てられない限り、実際に"Toyota"ofに設定しません。

1
Youans

もう1つの解決策が見つかりました。フィールドを開始済み最終ラッパーまたはプロキシにラップできます。 AtomicReferenceにラップする最も簡単な方法。

@Builder
public class Example {
    private String field1;
    private String field2;
    private final AtomicReference<String> excluded = new AtomicReference<>(null);
}

Getメソッドとsetメソッドを使用して内部で操作できますが、ビルダーには表示されません。

excluded.set("Some value");
excluded.get();
1
kattoha