lombok @data 忽略属性_使用lombok编写优雅的Bean对象
題外話(huà):歡迎將公眾號(hào)設(shè)置為星標(biāo),技術(shù)文章第一時(shí)間看到。我們將一如既往精選技術(shù)好文,提供有價(jià)值的閱讀。如有讀者想要投稿,可以在公眾號(hào)任意文章下留言,技術(shù)博主獎(jiǎng)勵(lì)豐厚。
推薦閱讀
1.?SpringBoot 整合篇
2.?手寫(xiě)一套迷你版HTTP服務(wù)器
3.?記住:永遠(yuǎn)不要在MySQL中使用UTF-8
4.?Springboot啟動(dòng)原理解析
使用java編寫(xiě)代碼,十之八九都是在寫(xiě)java類(lèi),從而構(gòu)建java對(duì)象。lombok之前也說(shuō)了不少,但使用了這么多年,感覺(jué)還是有很多技巧可以使用的。
毫無(wú)疑問(wèn),使用lombok,編寫(xiě)的java代碼很優(yōu)雅,而使用起來(lái)和普通的java編碼方式創(chuàng)建的類(lèi)毫無(wú)二致。不過(guò),這樣就滿(mǎn)足了嗎?實(shí)際上lombok很多注解,讓這個(gè)java類(lèi)在使用的時(shí)候,也可以更優(yōu)雅。
本文就從ORM實(shí)體類(lèi)、Builder模式工具類(lèi)、Wither工具類(lèi)以及Accessors工具類(lèi)幾個(gè)層面對(duì)比一下。
首先說(shuō)明,不同的方式本質(zhì)上沒(méi)有優(yōu)劣之分,不過(guò)在不同的應(yīng)用場(chǎng)景就會(huì)變得很奇妙了。
ORM實(shí)體類(lèi)
當(dāng)一個(gè)java Bean類(lèi)作為ORM實(shí)體類(lèi),或者xml、json的映射類(lèi)時(shí),需要這個(gè)類(lèi)有這幾個(gè)特征:
擁有無(wú)參構(gòu)造器
擁有setter方法,用以反序列化;
擁有g(shù)etter方法,用以序列化。
那么最簡(jiǎn)單的情況就是:
@Data復(fù)習(xí)一下,Data 注解相當(dāng)于裝配了 @Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode
那么,作為實(shí)體類(lèi)、或者序列化的Bean類(lèi),足夠用了。
Builder
構(gòu)造器模式,在很多工具類(lèi)中頻繁的使用。
package?com.pollyduan.builder;它做了什么事?
它創(chuàng)建了一個(gè)private 的全參構(gòu)造器。也就意味著 無(wú)參構(gòu)造器沒(méi)有; 同時(shí)也意味著這個(gè)類(lèi)不可以直接構(gòu)造對(duì)象。
它為每一個(gè)屬性創(chuàng)建了一個(gè)同名的方法用于賦值,代替了setter,而該方法的返回值為對(duì)象本身。
使用一下:
UserBean?u=UserBean.builder()????.id(1001)
????.userName("polly")
????.build();
System.out.println(u);
還不錯(cuò),然并卵,由于這個(gè)Bean并沒(méi)有g(shù)etter方法,里邊的數(shù)據(jù)沒(méi)辦法直接使用。光說(shuō)沒(méi)用,繼續(xù)執(zhí)行你會(huì)發(fā)現(xiàn)輸出是這個(gè)東西:com.pollyduan.builder.UserBean@20322d26,連看都看不出是什么東東。因此,Builder提供了一個(gè)種可能性,實(shí)際使用還需要更多的東西。
那么,我們?yōu)榱藴y(cè)試方便需要添加 @ToString() 注解,就會(huì)輸出 UserBean(id=1001, userName=polly)
換一個(gè)思路,你可能想,我不添加ToString注解,我把他轉(zhuǎn)成json輸出:
UserBean?u=UserBean.builder()????.id(1001)
????.userName("polly")
????.build();
ObjectMapper?mapper=new?ObjectMapper();
System.out.println(mapper.writeValueAsString(u));
很不幸,你會(huì)收到下面的異常:
com看到 no properties discovered 了吧,沒(méi)錯(cuò),工具類(lèi)無(wú)法找到屬性,因?yàn)闆](méi)有 getter,那么我們加上 @Getter 就可以了。
package?com.pollyduan.builder;序列化為json可以了,那么從一個(gè)json反序列化為對(duì)象呢?
@Builder還是不行,如無(wú)意外,會(huì)遇到
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance ofcom.pollyduan.builder.UserBean(no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
前面已經(jīng)交代了,光增加 @Setter 還不夠,他還需要一個(gè)無(wú)參構(gòu)造器。那么,下面可以嗎?
package?com.pollyduan.builder;同樣不行,因?yàn)殡m然 Data使用的時(shí)候可以直接使用無(wú)參構(gòu)造器,但由于 Builder 引入了全參構(gòu)造器,那么按照java原生的規(guī)則,無(wú)參構(gòu)造器就沒(méi)有了。那么就再加一個(gè)無(wú)參構(gòu)造器
@Builder@Data
@NoArgsConstructor
很不幸,Builder又報(bào)錯(cuò)了,它找不到全參構(gòu)造器了。好吧,最終的效果如下:
@Builder注意全參構(gòu)造器的訪問(wèn)級(jí)別,不要破壞Builder的規(guī)則。
更進(jìn)一步,看如下示例:
package?com.pollyduan.builder;思考一下,這個(gè)List 我們也需要在外面new 一個(gè) ArrayList,然后build進(jìn)去,使用起來(lái)并不舒服。lombok提供了另一個(gè)注解配合使用,那就是 @Singular,如下:
package?com.pollyduan.builder;那么就可以這樣操作這個(gè)列表了。
UserBean?u?=?UserBean.builder()是不是很方便?同時(shí)還提供了一個(gè) clearXXX方法,清空集合。
還有一個(gè)小坑,如果我們?cè)黾右粋€(gè)example屬性,然后給它一個(gè)默認(rèn)值:
@Builder測(cè)試一下看:
UserBean?u?=?UserBean.builder()????.id(1001)
????.userName("polly")
????.build();
System.out.println(u.toString());
輸出結(jié)果:UserBean(id=1001, userName=polly, example=null)
咦,不對(duì)呀?缺省值呢??這要從Builder的原理來(lái)解釋,他實(shí)際上是分別設(shè)置了一套屬性列表的值,然后使用全參構(gòu)造器創(chuàng)建對(duì)象。那么,默認(rèn)值在Bean上,不在Builder上,那么Builder沒(méi)賦值,它的值就是null,最后把所有屬性都復(fù)制給UserBean,從而null覆蓋了默認(rèn)值。
如何讓Builder實(shí)體來(lái)有默認(rèn)值呢?只需要給該字段增加 @Default 注解級(jí)可。
package?com.pollyduan.builder;重新執(zhí)行測(cè)試用例,輸出:UserBean(id=1001, userName=polly, example=123456),OK,沒(méi)毛病了。
Wither
用wither方式構(gòu)建對(duì)象,這在Objective-C 中比較多見(jiàn)。
適用的場(chǎng)景是,使用幾個(gè)必要的參數(shù)構(gòu)建對(duì)象,其他參數(shù),動(dòng)態(tài)的拼裝。舉個(gè)例子,我們構(gòu)建一個(gè)ApiClient,它的用戶(hù)名和密碼是必須的,他的ApiService的地址有一個(gè)默認(rèn)值,然后我們可以自己定制這個(gè)地址。
package?com.pollyduan.wither;如何使用呢?
Testpublic?void?test1()?{默認(rèn)的使用null去初始化一個(gè)對(duì)象還是很奇怪的。和 Builder一樣,Wither也是提供了可能性,實(shí)際使用還需要調(diào)整一下。
我們可以設(shè)置一個(gè)必選參數(shù)的構(gòu)造器,如下:
package?com.pollyduan.wither;這樣使用時(shí)就可以這樣:
Testpublic?void?test1()?{是不是優(yōu)雅了很多?而且實(shí)際上使用時(shí)也使用鏈?zhǔn)秸Z(yǔ)法:
new?ApiClient(另外還有一個(gè)小細(xì)節(jié),前面的示例輸出如下:
com這個(gè)日志表明,with() 返回的對(duì)象并不是原來(lái)的對(duì)象,而是一個(gè)新對(duì)象,這很重要。
Accessors
訪問(wèn)器模式,是給一個(gè)普通的Bean增加一個(gè)便捷的訪問(wèn)器,包括讀和寫(xiě)。
它有兩種工作模式,fluent和chain,舉例說(shuō)明:
package?com.pollyduan.accessors;使用代碼:
new?UserBean()這和 Builder 類(lèi)似,但更小巧,而且不影響屬性的讀寫(xiě),只不過(guò)使用屬性同名字符串代替了getter和setter。
另一個(gè)模式是 chain:
new?UserBean()可以看得出來(lái),這fluent的區(qū)別就在于使用getter和setter。
作者:polly
my.oschina.net/polly/blog/3040750
與50位技術(shù)專(zhuān)家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的lombok @data 忽略属性_使用lombok编写优雅的Bean对象的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: mysql 拼接sql批量执行_MySq
- 下一篇: date类before()方法的主要作用