web-dev-qa-db-fra.com

Comment exclure une propriété du constructeur Lombok?

J'ai une classe appelée "XYZClientWrapper", qui a la structure suivante:

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

Ce que je veux, aucune fonction de génération générée pour la propriété XYZClient client 

Est-ce que Lombok prend en charge un tel cas d'utilisation?

30
Vivek Goel

Oui, vous pouvez placer @Builder sur un constructeur ou une méthode statique (fabrique) contenant uniquement les champs de votre choix. 

Divulgation: Je suis un développeur de Lombok.

65
Roel Spilker

Sinon, j'ai découvert que le marquage d'un champ par final , static ou static final indique à @Builder d'ignorer ce champ.

@Builder
public class MyClass {
   private String myField;

   private final String excludeThisField = "bar";
}

Lombok 1.16.10

6
Stephan

J'ai constaté que j'étais capable d'implémenter un "Shell" de la classe Builder statique, d'ajouter la méthode que je veux masquer avec un modificateur d'accès privé et qu'elle n'est plus accessible dans le générateur. De même, je peux également ajouter des méthodes personnalisées au générateur.

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
Richard Collette

Créez le générateur dans le code et ajoutez un passeur privé pour votre propriété.

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

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

Exemple de méthode statique en usine

Class Car{
   private String name;
   private String model;


   private Engine engine; // we want to ignore 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}
}

alors vous pouvez utiliser comme suit:

main(String[] args){

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

}

Notez que la méthode statique of sera appelée chaque fois que build () est appelé. Par conséquent, une action telle que Car.builder().name("Toyota") ne définit pas la valeur "Toyota" dans name à moins que build() ne soit appelé, puis l'assignation de la logique dans la méthode statique constructeur of est exécutée.

0
YouYou

Voici ma solution préférée. Avec cela, vous pouvez créer votre champ client à la fin et le définir en fonction d'autres champs préalablement définis par le générateur.

XYZClientWrapper{
    String name;
    String domain;
    XYZClient client;

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