小編給大家分享一下java如何使用Lombok更優(yōu)雅地編碼,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)!專(zhuān)注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、小程序制作、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶(hù)創(chuàng)新互聯(lián)還提供了宜州免費(fèi)建站歡迎大家使用!
Lombok簡(jiǎn)介
和其他語(yǔ)言相比,Java經(jīng)常因?yàn)椴槐匾娜唛L(zhǎng)被批評(píng)。Lombok提供了一系列注解用以在后臺(tái)生成模板代碼,將其從你的類(lèi)中刪除,從而有助于保持你的代碼整潔。較少的模板意味著更簡(jiǎn)潔的代碼,更易于閱讀和維護(hù)。在本文中,我將涉及我經(jīng)常使用的Lombok功能,并想你展示如何使用他們生產(chǎn)更清晰、更簡(jiǎn)潔的代碼。
1.局部變量類(lèi)型推斷:val 和 var
許多語(yǔ)言通過(guò)查看等號(hào)右側(cè)的表達(dá)式來(lái)推斷局部變量類(lèi)型。盡管現(xiàn)在Java 10+已經(jīng)支持這種功能,但在之前的版本中沒(méi)有Lombok的幫助就無(wú)法實(shí)現(xiàn)。下面的代碼段展示了如何顯式指定局部類(lèi)型:
final Mapmap = new HashMap<>(); map.put("Joe", 21);
在Lombok中,我們可以通過(guò)使用val來(lái)縮短它,如下所示:
val valMap = new HashMap(); valMap.put("Sam", 30);
注意,val在背后創(chuàng)建了一個(gè)final且不可變的變量。如果你需要一個(gè)可變本地變量,可以使用var。
2.@NonNull
對(duì)方法參數(shù)進(jìn)行null檢查通常不是一個(gè)壞主意,特別是如果該方法形成的API被其他開(kāi)發(fā)者使用。雖然這些檢查很簡(jiǎn)單,但是他們可能變得冗長(zhǎng),特別是當(dāng)你有多個(gè)參數(shù)時(shí)。如下所示,額外的代碼無(wú)助于可讀性,并且可能從方法的主要目的分散注意力。
public void nonNullDemo(Employee employee, Account account) { if(employee == null) { throw new IllegalArgumentException("Employee is marked @NonNull but is null"); } if(account == null) { throw new IllegalArgumentException("Account is marked @NonNull but is null"); } // do stuff }
理想情況下,你需要null檢查——沒(méi)有干擾的那種。這就是@NonNull發(fā)揮作用的地方。通過(guò)用@NonNull標(biāo)記參數(shù),Lombok替你為該參數(shù)生成null檢查。你的方法突然變得更加簡(jiǎn)潔,但沒(méi)有丟失那些安全性的null檢查。
public void nonNullDemo(@NonNull Employee employee, @NonNull Account account) { // just do stuff }
默認(rèn)情況下,Lombok會(huì)拋出NullPointerException,如果你愿意,可以配置 Lombok拋出IllegalArgumentException。我個(gè)人更喜歡IllegalArgumentException,因?yàn)槲艺J(rèn)為它更適合于對(duì)參數(shù)檢查。
##3.更簡(jiǎn)潔的數(shù)據(jù)類(lèi) 數(shù)據(jù)類(lèi)是Lombok真正有助于減少模板代碼的領(lǐng)域。在查看該選項(xiàng)前,思考一下我們經(jīng)常需要處理的模板種類(lèi)。數(shù)據(jù)類(lèi)通常包括以下一種或全部:
構(gòu)造函數(shù)(有或沒(méi)有參數(shù))
私有成員變量的 getter 方法
私有非 final 成員變量的 setter 方法
幫助記錄日志的 toString 方法
equals 和 hashCode(處理相等/集合)
可以通過(guò) IDE 生成以上內(nèi)容,因此問(wèn)題不在于編寫(xiě)他們花費(fèi)的時(shí)間。問(wèn)題是帶有少量成員變量的簡(jiǎn)單類(lèi)很快會(huì)變得非常冗長(zhǎng)。讓我們看看Lombok如何通過(guò)處理上述的每一項(xiàng)來(lái)減少混亂。
3.1. @Getter 和 @Setter
想想下面的Car類(lèi)。當(dāng)生成getter和setter時(shí),我們會(huì)得到接近 50 行代碼來(lái)描述一個(gè)包含 5 個(gè)成員變量的類(lèi)。
public class Car { private String make; private String model; private String bodyType; private int yearOfManufacture; private int cubicCapacity; public String getMake() { return make; } public void setMake(String make) { this.make = make; } public String getModel() { return model; } public void setModel(String model) { this.model = model; } public String getBodyType() { return bodyType; } public void setBodyType(String bodyType) { this.bodyType = bodyType; } public int getYearOfManufacture() { return yearOfManufacture; } public void setYearOfManufacture(int yearOfManufacture) { this.yearOfManufacture = yearOfManufacture; } public int getCubicCapacity() { return cubicCapacity; } public void setCubicCapacity(int cubicCapacity) { this.cubicCapacity = cubicCapacity; } }
Lombok可以替你生成getter和setter模板。通過(guò)對(duì)每個(gè)成員變量使用 @Getter和@Setter注解,你最終得到一個(gè)等效的類(lèi),如下所示:
public class Car { @Getter @Setter private String make; @Getter @Setter private String model; @Getter @Setter private String bodyType; @Getter @Setter private int yearOfManufacture; @Getter @Setter private int cubicCapacity; }
注意,你可以在非final成員變量上只使用@Setter。在final成員變量上使用它將導(dǎo)致編譯錯(cuò)誤。
如果你需要為每個(gè)成員變量生成getter和setter,你也可以在類(lèi)級(jí)別使用 @Getter和@Setter,如下所示。
@Getter @Setter public class Car { private String make; private String model; private String bodyType; private int yearOfManufacture; private int cubicCapacity; }
3.2. @AllArgsConstructor
數(shù)據(jù)類(lèi)通常包含一個(gè)構(gòu)造函數(shù),它為每個(gè)成員變量接受參數(shù)。IDE 為Car生成的構(gòu)造函數(shù)如下所示:
public class Car { @Getter @Setter private String make; @Getter @Setter private String model; @Getter @Setter private String bodyType; @Getter @Setter private int yearOfManufacture; @Getter @Setter private int cubicCapacity; public Car(String make, String model, String bodyType, int yearOfManufacture, int cubicCapacity) { super(); this.make = make; this.model = model; this.bodyType = bodyType; this.yearOfManufacture = yearOfManufacture; this.cubicCapacity = cubicCapacity; } }
我們可以使用@AllArgsConstructor注解實(shí)現(xiàn)同樣功能。@Getter和 @Setter、@AllArgsConstructor減少模板,保持類(lèi)更干凈且更簡(jiǎn)潔。
@AllArgsConstructor public class Car { @Getter @Setter private String make; @Getter @Setter private String model; @Getter @Setter private String bodyType; @Getter @Setter private int yearOfManufacture; @Getter @Setter private int cubicCapacity; }
還有其他選項(xiàng)用于生成構(gòu)造函數(shù)。@RequiredArgsConstructor將創(chuàng)建帶有每個(gè) final成員變量參數(shù)的構(gòu)造函數(shù),@NoArgsConstructor將創(chuàng)建沒(méi)有參數(shù)的構(gòu)造函數(shù)。
3.3. @ToString
在你的數(shù)據(jù)類(lèi)上覆蓋toString方法是有助于記錄日志的良好實(shí)踐。IDE 為Car類(lèi)生成的toString方法如下所示:
@AllArgsConstructor public class Car { @Getter @Setter private String make; @Getter @Setter private String model; @Getter @Setter private String bodyType; @Getter @Setter private int yearOfManufacture; @Getter @Setter private int cubicCapacity; @Override public String toString() { return "Car [make=" + make + ", model=" + model + ", bodyType=" + bodyType + ", yearOfManufacture=" + yearOfManufacture + ", cubicCapacity=" + cubicCapacity + "]"; } }
我們可以使用ToString注解廢除這個(gè),如下所示:
@ToString @AllArgsConstructor public class Car { @Getter @Setter private String make; @Getter @Setter private String model; @Getter @Setter private String bodyType; @Getter @Setter private int yearOfManufacture; @Getter @Setter private int cubicCapacity; }
默認(rèn)情況下,Lombok生成包含所有成員變量的toString方法??梢酝ㄟ^(guò) exclude屬性@ToString(exclude={"someField"}, "someOtherField"}) 覆蓋行為將某些成員變量排除。
3.4. @EqualsAndHashCode
如果你正在將你的數(shù)據(jù)類(lèi)和任何類(lèi)型的對(duì)象比較,則需要覆蓋equals和hashCode 方法。對(duì)象的相等是基于業(yè)務(wù)規(guī)則定義的。舉個(gè)例子,在Car類(lèi)中,如果兩個(gè)對(duì)象有相同的make、model和bodyType,我可能認(rèn)為他們是相等的。如果我使用 IDE 生成equals方法檢查make、model和bodyType,它看起來(lái)會(huì)是這樣:
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Car other = (Car) obj; if (bodyType == null) { if (other.bodyType != null) return false; } else if (!bodyType.equals(other.bodyType)) return false; if (make == null) { if (other.make != null) return false; } else if (!make.equals(other.make)) return false; if (model == null) { if (other.model != null) return false; } else if (!model.equals(other.model)) return false; return true; }
等價(jià)的hashCode實(shí)現(xiàn)如下所示:
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((bodyType == null) ? 0 : bodyType.hashCode()); result = prime * result + ((make == null) ? 0 : make.hashCode()); result = prime * result + ((model == null) ? 0 : model.hashCode()); return result; }
雖然 IDE 處理了繁重的工作,但我們?cè)陬?lèi)中仍然有大量的模板代碼。Lombok允許我們使用@EqualsAndHashCode類(lèi)注解實(shí)現(xiàn)相同的功能,如下所示:
@ToString @AllArgsConstructor @EqualsAndHashCode(exclude = { "yearOfManufacture", "cubicCapacity" }) public class Car { @Getter @Setter private String make; @Getter @Setter private String model; @Getter @Setter private String bodyType; @Getter @Setter private int yearOfManufacture; @Getter @Setter private int cubicCapacity; }
默認(rèn)情況下,@EqualsAndHashCode會(huì)創(chuàng)建包含所有成員變量的equals和 hashCode方法。exclude選項(xiàng)可用于通知Lombok排除某些成員變量。
在上面的代碼片段中。我已經(jīng)從生成的equals和hashCode方法中排除了 yearOfManuFacture 和cubicCapacity。
3.5. @Data
如果你想使數(shù)據(jù)類(lèi)盡可能精簡(jiǎn),可以使用@Data注解。@Data 是@Getter、@Setter、@ToString、@EqualsAndHashCode 和 @RequiredArgsConstructor 的快捷方式。
@ToString @RequiredArgsConstructor @EqualsAndHashCode(exclude = { "yearOfManufacture", "cubicCapacity" }) public class Car { @Getter @Setter private String make; @Getter @Setter private String model; @Getter @Setter private String bodyType; @Getter @Setter private int yearOfManufacture; @Getter @Setter private int cubicCapacity; }
通過(guò)使用@Data,我們可以將上面的類(lèi)精簡(jiǎn)如下:
@Data public class Car { private String make; private String model; private String bodyType; private int yearOfManufacture; private int cubicCapacity; }
4. 使用 @Buidler 創(chuàng)建對(duì)象
建造者設(shè)計(jì)模式描述了一種靈活的創(chuàng)建對(duì)象的方式。Lombok可以幫你輕松的實(shí)現(xiàn)該模式。看一個(gè)使用簡(jiǎn)單Car類(lèi)的示例。假設(shè)我們希望可以創(chuàng)建各種Car對(duì)象,但我們希望在創(chuàng)建時(shí)設(shè)置的屬性具有靈活性。
@AllArgsConstructor public class Car { private String make; private String model; private String bodyType; private int yearOfManufacture; private int cubicCapacity; private ListserviceDate; }
假設(shè)我們要?jiǎng)?chuàng)建一個(gè)Car,但只想設(shè)置make和model。在Car上使用標(biāo)準(zhǔn)的全參數(shù)構(gòu)造函數(shù)意味著我們只提供make和model并設(shè)置其他參數(shù)為null。
Car2 car2 = new Car2("Ford", "Mustang", null, null, null, null);
這可行但并不理想,我們必須為我們不感興趣的參數(shù)傳遞null。我們可以創(chuàng)建一個(gè)只接受make和model的構(gòu)造函數(shù)來(lái)避開(kāi)這個(gè)問(wèn)題。這是一個(gè)合理的解決方法,但不夠靈活。如果我們有許多不同的字段排列,我們可以用什么來(lái)創(chuàng)建一個(gè)新Car?最終我們得到了一堆不同的構(gòu)造函數(shù),代表了我們可以實(shí)例化Car的所有可能方式。
解決該問(wèn)題的一種干凈、靈活的方式是使用建造者模式。Lombok通過(guò)@Builder 注解幫你實(shí)現(xiàn)建造者模式。當(dāng)你使用@Builder注解Car類(lèi)時(shí),Lombok會(huì)執(zhí)行以下操作:
添加一個(gè)私有構(gòu)造函數(shù)到Car
創(chuàng)建一個(gè)靜態(tài)的CarBuilder類(lèi)
在CarBuilder中為Car中的每個(gè)成員創(chuàng)建一個(gè)setter風(fēng)格方法。
在CarBuilder中添加創(chuàng)建Car的新實(shí)例的建造方法。
CarBuilder上的每個(gè)setter風(fēng)格方法返回自身的實(shí)例(CarBuilder)。這允許你進(jìn)行方法鏈?zhǔn)秸{(diào)用并為對(duì)象創(chuàng)建提供流暢的 API。讓我們看看它如何使用。
Car muscleCar = Car.builder().make("Ford") .model("mustang") .bodyType("coupe") .build();
現(xiàn)在只使用make和model創(chuàng)建Car比之前更簡(jiǎn)潔了。只需在Car上簡(jiǎn)單的調(diào)用生成的builder方法獲取CarBuilder實(shí)例,然后調(diào)用任何我們感興趣的setter風(fēng)格方法。最后,調(diào)用build創(chuàng)建Car的新實(shí)例。
另一個(gè)值得一提的方便的注解是@Singular。默認(rèn)情況下,Lombok 為集合創(chuàng)建使用集合參數(shù)的標(biāo)準(zhǔn)的 setter 風(fēng)格方法。在下面的例子中,我們創(chuàng)建了新的 Car并設(shè)置了服務(wù)日期列表。
Car muscleCar = Car.builder().make("Ford") .model("mustang") .serviceDate(Arrays.asList(LocalDate.of(2016, 5, 4))) .build();
向集合成員變量添加@Singular將提供一個(gè)額外的方法,允許你向集合添加單個(gè)項(xiàng)。
@Builder public class Car { private String make; private String model; private String bodyType; private int yearOfManufacture; private int cubicCapacity; @Singular private ListserviceDate; }
現(xiàn)在我們可以添加單個(gè)服務(wù)日期,如下所示:
Car muscleCar3 = Car.builder() .make("Ford") .model("mustang") .serviceDate(LocalDate.of(2016, 5, 4)) .build();
這是一個(gè)有助于在創(chuàng)建對(duì)象期間處理集合時(shí)保持代碼簡(jiǎn)潔的快捷方法。
5.日志
Lombok另一個(gè)偉大的功能是日志記錄器。如果沒(méi)有Lombok,要實(shí)例化標(biāo)準(zhǔn)的 SLF4J日志記錄器,通常會(huì)有以下內(nèi)容:
public class SomeService { private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class); public void doStuff(){ log.debug("doing stuff...."); } }
這些日志記錄器很沉重,并為每個(gè)需要日志記錄的類(lèi)添加了不必要的混亂。值得慶幸的是 Lombok提供了一個(gè)為你創(chuàng)建日志記錄器的注解。你要做的所有事情就是在類(lèi)上添加注解,這樣就可以了。
@Slf4j public class SomeService { public void doStuff(){ log.debug("doing stuff...."); } }
我在這里使用了@SLF4J注解,但Lombok能為幾乎所有通用Java日志框架生成日志記錄器。有關(guān)更多日志記錄器的選項(xiàng),請(qǐng)參閱文檔。
6.Lombok給你控制權(quán)
我非常喜歡Lombok的一點(diǎn)是它的不侵入性。。如果你決定在使用如@Getter、@Setter 或 @ToString時(shí)也想要自己的方法實(shí)現(xiàn),你的方法將總是優(yōu)先于 Lombok。它允許你在大多數(shù)時(shí)間使用Lombok,但在你需要的時(shí)候仍有控制權(quán)。
以上是“java如何使用Lombok更優(yōu)雅地編碼”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!