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