问题
I have a class called as "XYZClientWrapper" , which have following structure:
@Builder
XYZClientWrapper{
String name;
String domain;
XYZClient client;
}
What I want no build function generated for property XYZClient client
Does Lombok supports such use case?
回答1:
Yes, you can place @Builder on a constructor or static (factory) method, containing just the fields you want.
Disclosure: I am a Lombok developer.
回答2:
Alternatively, I found out that marking a field as final, static or static final instructs @Builder
to ignore this field.
@Builder
public class MyClass {
private String myField;
private final String excludeThisField = "bar";
}
Lombok 1.16.10
回答3:
Create the builder in code and add a private setter for your property.
@Builder
XYZClientWrapper{
String name;
String domain;
XYZClient client;
public static class XYZClientWrapperBuilder {
private XYZClientWrapperBuilder client(XYZClient client) { return this; }
}
}
回答4:
I found that I was able to implement a "shell" of the static Builder class, add the method I want to hide with a private access modifier, and it is no longer accessible in the builder. Likewise I can add custom methods to the builder as well.
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:
Here is my preferred solution. With that, you can create your field client
at the end and have it depending on other fields that previously set by the builder.
XYZClientWrapper{
String name;
String domain;
XYZClient client;
@Builder
public XYZClientWrapper(String name, String domain) {
this.name=name;this.domain=domain;
this.client=calculateClient();
}
}
回答6:
I found one more solution You can wrap your field into initiated final wrapper or proxy. The easiest way to wrap it into AtomicReference.
@Builder
public class Example {
private String field1;
private String field2;
private final AtomicReference<String> excluded = new AtomicReference<>(null);
}
You can interact with it inside by get and set methods but it won't be appeared in builder.
excluded.set("Some value");
excluded.get();
回答7:
For factory static method example
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
}
}
then you can use as follows:
Car toyotaCorollaCar=Car.builder().name("Toyota").model("Corolla").build();
// You can see now that Car.builder().engine() is not available
Notice the static method of
will be called whenever build() is called, so doing something like Car.builder().name("Toyota")
won't actually set the value "Toyota"
into name
unless build()
is called and then assigning logic within the constructor static method of
is executed.
Also, Notice that the of
method is privately accessed so that build
method is the only method visible to the callers
来源:https://stackoverflow.com/questions/30717640/how-to-exclude-property-from-lombok-builder