lombok @Builder注解的使用
@Builder
......鮑勃是你的叔叔:用于創(chuàng)建對象的無懈可擊的花式褲子!
@Builder 在lombok v0.12.0中作為實驗特征介紹。
@Builder獲得了@Singular支持,并lombok從lombok v1.16.0 升級到主程序包。
@Builder與@Singular增加,因為龍目島v1.16.8一個明確的方法。
@Builder.Default 功能已在lombok v1.16.16中添加。
Overview
該@Builder標注生產(chǎn)絡(luò)合劑的API為你的類。
@Builder 允許您使用以下代碼自動生成使您的類可實例化所需的代碼:
Person.builder().name("Adam Savage").city("San Francisco").job("Mythbusters").job("Unchained Reaction").build();
@Builder可以放在類,構(gòu)造函數(shù)或方法上。雖然“在類上”和“在構(gòu)造函數(shù)上”模式是最常見的用例,但@Builder最容易用“方法”用例來解釋。
用@Builder(從現(xiàn)在開始調(diào)用目標)注釋的方法會導(dǎo)致生成以下7件事:
- 一個名為的內(nèi)部靜態(tài)類*Foo*Builder,具有與靜態(tài)方法相同的類型參數(shù)(稱為構(gòu)建器)。
- 在構(gòu)建器中:目標的每個參數(shù)的一個私有非靜態(tài)非最終字段。
- 在構(gòu)建器中:一個包私有no-args空構(gòu)造函數(shù)。
- 在構(gòu)建器中:對于目標的每個參數(shù),類似于“setter”的方法:它具有與該參數(shù)相同的類型和相同的名稱。它返回構(gòu)建器本身,以便可以鏈接setter調(diào)用,如上例所示。
- 在構(gòu)建器中:build()調(diào)用方法的方法,傳入每個字段。它返回與目標返回的相同類型。
- 在構(gòu)建器中:一個明智的toString()實現(xiàn)。
- 在包含目標的類中:一種builder()方法,它創(chuàng)建構(gòu)建器的新實例。
如果該元素已經(jīng)存在,則將以靜默方式跳過每個列出的生成元素(忽略參數(shù)計數(shù)并僅查看名稱)。這包括構(gòu)建器本身:如果該類已經(jīng)存在,則lombok將簡單地開始在此已存在的類中注入字段和方法,除非當然要存在要注入的字段/方法。您可能不會在構(gòu)建器類上放置任何其他方法(或構(gòu)造函數(shù))生成lombok注釋; 例如,您不能放置@EqualsAndHashCode構(gòu)建器類。
@Builder可以為集合參數(shù)/字段生成所謂的“奇異”方法。它們采用1個元素而不是整個列表,并將該元素添加到列表中。例如:Person.builder().job("Mythbusters").job("Unchained Reaction").build();將導(dǎo)致該List<String> jobs字段中包含2個字符串。要獲得此行為,需要使用注釋字段/參數(shù)@Singular。該功能有自己的文檔。
既然“方法”模式已經(jīng)清楚了,那么@Builder在構(gòu)造函數(shù)上添加注釋的功能類似; 實際上,構(gòu)造函數(shù)只是具有特殊語法來調(diào)用它們的靜態(tài)方法:它們的“返回類型”是它們構(gòu)造的類,它們的類型參數(shù)與類本身的類型參數(shù)相同。
最后,應(yīng)用于@Builder類就好像您已添加@AllArgsConstructor(access = AccessLevel.PACKAGE)到類中并將@Builder注釋應(yīng)用于此all-args構(gòu)造函數(shù)。這僅適用于您自己沒有編寫任何顯式構(gòu)造函數(shù)的情況。如果您確實有一個顯式構(gòu)造函數(shù),請將@Builder注釋放在構(gòu)造函數(shù)而不是類上。
如果使用@Builder生成構(gòu)建器來生成自己的類的實例(除非添加@Builder到不返回自己類型的方法,否則總是如此),您可以使用@Builder(toBuilder = true)在類中生成實例方法調(diào)用toBuilder(); 它會創(chuàng)建一個以該實例的所有值開頭的新構(gòu)建器。您可以將@Builder.ObtainVia注釋放在參數(shù)(如果是構(gòu)造函數(shù)或方法)或字段(如果@Builder是類型)上,以指示從該實例獲取該字段/參數(shù)的值的替代方法。例如,您可以指定要調(diào)用的方法:@Builder.ObtainVia(method = "calculateFoo")。
構(gòu)建器類的名稱是*Foobar*Builder,其中Foobar是目標返回類型的簡化,標題框形式- 即@Builder構(gòu)造函數(shù)和類型的類型名稱,以及@Builderon方法的返回類型的名稱。例如,如果@Builder應(yīng)用于名為的類com.yoyodyne.FancyList<T>,則構(gòu)建器名稱將為FancyListBuilder<T>。如果@Builder應(yīng)用于返回的方法,void則將命名構(gòu)建器VoidBuilder。
構(gòu)建器的可配置方面是:
- 該生成器的類名(默認:返回類型+“生成器”)
- 該版本()方法的名稱(默認:"build")
- 該生成器()方法的名稱(默認:"builder")
- 如果你想toBuilder()(默認:否)
所有選項均從其默認值更改的示例用法:
@Builder(builderClassName = "HelloWorldBuilder", buildMethodName = "execute", builderMethodName = "helloWorld", toBuilder = true)
@Builder.Default
如果在構(gòu)建會話期間從未設(shè)置某個字段/參數(shù),則它始終為0 / null/ false。如果您已經(jīng)放置@Builder了一個類(而不是方法或構(gòu)造函數(shù)),則可以直接在該字段上指定默認值,并使用以下內(nèi)容對該字段進行注釋@Builder.Default:
@Builder.Default private final long created = System.currentTimeMillis();
@Singular
通過使用注釋注釋其中一個參數(shù)(如果使用方法或構(gòu)造函數(shù)進行注釋@Builder)或字段(如果使用注釋類@Builder)@Singular,lombok將該構(gòu)建器節(jié)點視為集合,并生成2個“加法器”方法而不是“ setter'方法。一個向集合添加單個元素,另一個將另一個集合的所有元素添加到集合中。將不生成僅設(shè)置集合(替換已添加的任何內(nèi)容)的setter。還生成了“清晰”方法。這些“單一”構(gòu)建器非常復(fù)雜,以保證以下屬性:
- 調(diào)用時build(),生成的集合將是不可變的。
- 在調(diào)用之后調(diào)用“adder”方法之一或“clear”方法build()不會修改任何已生成的對象,并且如果build()稍后再次調(diào)用,則會生成自生成構(gòu)建器以來添加了所有元素的另一個集合。
- 生成的集合將被壓縮到最小的可行格式,同時保持高效。
@Singular只能應(yīng)用于lombok已知的集合類型。目前,支持的類型是:
- java.util:
- Iterable,Collection和List(ArrayList在一般情況下由壓縮的不可修改的支持)。
- Set,SortedSet和NavigableSet(由一個聰明的大小不可修改HashSet或TreeSet在一般情況下支持)。
- Map,SortedMap和NavigableMap(由一個聰明的大小不可修改HashMap或TreeMap在一般情況下支持)。
- 番石榴的com.google.common.collect:
- ImmutableCollection和ImmutableList(由構(gòu)建器功能支持ImmutableList)。
- ImmutableSet和ImmutableSortedSet(由這些類型的構(gòu)建器功能支持)。
- ImmutableMap,ImmutableBiMap和ImmutableSortedMap(由這些類型的構(gòu)建器功能支持)。
- ImmutableTable(由構(gòu)建器功能支持ImmutableTable)。
如果您的標識符是用通用英語編寫的,則lombok假定其上的任何集合的名稱@Singular是英語復(fù)數(shù),并將嘗試自動單獨化該名稱。如果可以,add-one方法將使用此名稱。例如,如果調(diào)用了您的集合statuses,則會自動調(diào)用add-one方法status。您還可以通過將單數(shù)形式作為參數(shù)傳遞給注釋來明確指定標識符的單數(shù)形式,如下所示:@Singular("axis") List<Line> axes;。
如果lombok無法單獨標識您的標識符,或者它不明確,則lombok將生成錯誤并強制您明確指定單數(shù)名稱。
下面的代碼段沒有顯示lombok為@Singular字段/參數(shù)生成的內(nèi)容,因為它相當復(fù)雜。您可以在此處查看代碼段。
With Jackson
您可以自定義構(gòu)建器類的自定義部分,例如向構(gòu)建器類添加另一個方法,或者在構(gòu)建器類中注釋方法。Lombok將生成您不手動添加的所有內(nèi)容,并將其放入此構(gòu)建器類中。例如,如果您嘗試將jackson配置為對集合使用特定子類型,則可以編寫如下內(nèi)容:
@Value @Builder @JsonDeserialize(builder = JacksonExample.JacksonExampleBuilder.class) public class JacksonExample {@Singular private List<Foo> foos;@JsonPOJOBuilder(withPrefix = "")public static class JacksonExampleBuilder implements JacksonExampleBuilderMeta {}private interface JacksonExampleBuilderMeta {@JsonDeserialize(contentAs = FooImpl.class) JacksonExampleBuilder foos(List<? extends Foo> foos)} }With Lombok
import lombok.Builder; import lombok.Singular; import java.util.Set;@Builder public class BuilderExample {@Builder.Default private long created = System.currentTimeMillis();private String name;private int age;@Singular private Set<String> occupations; }Vanilla Java
import java.util.Set;public class BuilderExample {private long created;private String name;private int age;private Set<String> occupations;BuilderExample(String name, int age, Set<String> occupations) {this.name = name;this.age = age;this.occupations = occupations;}private static long $default$created() {return System.currentTimeMillis();}public static BuilderExampleBuilder builder() {return new BuilderExampleBuilder();}public static class BuilderExampleBuilder {private long created;private boolean created$set;private String name;private int age;private java.util.ArrayList<String> occupations;BuilderExampleBuilder() {}public BuilderExampleBuilder created(long created) {this.created = created;this.created$set = true;return this;}public BuilderExampleBuilder name(String name) {this.name = name;return this;}public BuilderExampleBuilder age(int age) {this.age = age;return this;}public BuilderExampleBuilder occupation(String occupation) {if (this.occupations == null) {this.occupations = new java.util.ArrayList<String>();}this.occupations.add(occupation);return this;}public BuilderExampleBuilder occupations(Collection<? extends String> occupations) {if (this.occupations == null) {this.occupations = new java.util.ArrayList<String>();}this.occupations.addAll(occupations);return this;}public BuilderExampleBuilder clearOccupations() {if (this.occupations != null) {this.occupations.clear();}return this;}public BuilderExample build() {// complicated switch statement to produce a compact properly sized immutable set omitted.Set<String> occupations = ...;return new BuilderExample(created$set ? created : BuilderExample.$default$created(), name, age, occupations);}@java.lang.Overridepublic String toString() {return "BuilderExample.BuilderExampleBuilder(created = " + this.created + ", name = " + this.name + ", age = " + this.age + ", occupations = " + this.occupations + ")";}} }Supported configuration keys:
lombok.builder.flagUsage = [warning | error] (default: not set)
lombok.singular.useGuava = [true | false] (default: false)
lombok.singular.auto = [true | false] (default: true)
Small print
@Singular支持java.util.NavigableMap/Set僅在您使用JDK1.8或更高版本進行編譯時才有效。
您無法手動提供@Singular節(jié)點的部分或全部部分; Lombok生成的代碼太復(fù)雜了。如果要手動控制(部分)與某個字段或參數(shù)關(guān)聯(lián)的構(gòu)建器代碼,請不要@Singular手動使用和添加所需的所有內(nèi)容。
排序集合(java.util中:SortedSet,NavigableSet,SortedMap,NavigableMap,番石榴:ImmutableSortedSet,ImmutableSortedMap)要求該集合的類型參數(shù)有自然順序(實現(xiàn)java.util.Comparable)。無法Comparator在構(gòu)建器中傳遞顯式內(nèi)容。
如果目標集合來自包,則 An ArrayList用于將添加的元素存儲為@Singular標記字段的調(diào)用方法java.util,即使集合是集合或映射也是如此。由于lombok確保生成的集合被壓縮,因此無論如何都必須構(gòu)建集合或映射的新后備實例,并且ArrayList在構(gòu)建過程中將數(shù)據(jù)存儲為將其存儲為映射或集合更有效。此行為不是外部可見的,是當前實現(xiàn)java.util配方的實現(xiàn)細節(jié)@Singular @Builder。
隨著toBuilder = true應(yīng)用到方法,注解的方法的任何類型的參數(shù)本身也必須在返回類型出現(xiàn)。
@Builder.Default刪除字段 上的初始化程序并將其存儲在靜態(tài)方法中,以確保在構(gòu)建中指定值時,根本不會執(zhí)行此初始化程序。這是否意味著初始化不能引用this,super或任何非靜態(tài)成員。如果lombok為您生成構(gòu)造函數(shù),它還將使用初始化程序初始化此字段。
各種眾所周知的關(guān)于nullity的注釋會導(dǎo)致插入空檢查,并將其復(fù)制到構(gòu)建器的'setter'方法的參數(shù)中。有關(guān)詳細信息,請參閱Getter / Setter文檔的小字體。
原文:https://www.jianshu.com/p/5e42ecede166
?
總結(jié)
以上是生活随笔為你收集整理的lombok @Builder注解的使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: springboot集成redis配置多
- 下一篇: springboot 定时任务注入线程池