lombok是一個編譯級别的插件,它可以在項目編譯的時候生成一些代碼。在很多工具類的項目中都有這個功能。比如dagger。
通俗的說,lombok可以通過注解來标示生成<code>getter</code> <code>settter</code>等代碼。我們自然可以通過編譯器比如IDEA的<code>Generate</code>生成,為啥要用這個?
在項目開發階段,一個class的屬性是一直變化的,今天可能增加一個字段,明天可能删除一個字段。每次變化都需要修改對應的模闆代碼。另外,有的class的字段超級多,多到一眼看不完。如果加上模闆代碼,更難一眼看出來。更有甚者,由于字段太多,想要使用builder來建立。手動建立builder和字段和原來的類夾雜在一起,看起來真的難受。lombok的<code>@Builder</code>即可解決這個問題。
引入就是加入<code>lombok</code>的jar包。
直接加入依賴
這裡比較麻煩,需要添加一個編譯時生成代碼的插件。gradle裡有幾個這樣的插件。但為了簡化過程,lombok提供了新插件。
首先,添加一個plugin
然後,就可以了。還可以配置lombok的版本:
在IDEA裡使用需要添加一個插件。在插件裡搜尋lombok,安裝,重新開機。
IDEA裡需要在設定中啟用annotation processors。
最簡單的,最常用的,最直覺的使用就是getter setter方法。
簡單使用沒有問題,深入一點可以看到有些特殊設定。比如javadoc.
<code>Getter</code>聲明建立getter方法;
<code>Setter</code>聲明建立setter方法;
<code>@Setter(AccessLevel.PROTECTED)</code>可以添加參數,指定權限為私有;
Attention!關于<code>boolean</code>的set字首都是set,但getter不同,小寫的<code>boolean</code>,即基本類型,字首是<code>is</code>; <code>Boolean</code>,即包裝類型,字首是<code>get</code>;
編譯後的結果如下:
1.<code>@ToString</code>最簡單使用即可
列印結果如下:
ToStringExample(name=abc, shape=ToStringExample.Square(super=ToStringExample.Shape(color=0), width=1, height=2), tags=[a, b, c])
編譯後的代碼如下:
equals()和hashCode()在Java中有着舉足輕重的基地作用,雖然通常很少關注。但是,這個必須不可省。不知道有幾個可以手寫出來的。
編譯後的結果為:
Java中class的一切起源于構造器。大家最喜歡的還是構造函數建立對象。這裡有一點比較坑的是無參構造函數。當你自己添加一個帶有參數的構造函數後,無參構造函數則别隐藏。通常也沒啥問題,但當你使用jackson反序列化對象的時候就被惡心到了。jackson通過無參構造函數建立對象。是以,當你考慮這個class會用來序列化為json的時候,即必須手動添加一個無參數構造函數。
當你想要建立一個valueobject,DDD中的值對象,要求實作Immutable,那麼無參數構造器就不合适了。<code>@NoArgsConstructor</code>會生成一個空的構造器。如果你設定了final field,那麼編譯會報錯。如果你強制執行建立無參數構造器。即,<code>@NoArgsConstructor(force = true)</code>,那麼final的field會初始化為<code>0</code>/<code>false</code>/<code>null</code>。通常适合與<code>@Data</code>內建。
<code>NonNull</code>被忽略了
最終生成代碼如下:
對于final的字段,我認為我不會用空構造器來做這件事。是以,感覺這個參數<code>force=true</code>不要也罷,雞肋。
一個class可以有很多屬性,但你可能隻關心其中的幾個字段,那麼可以使用<code>@RequiredArgsConstructor</code>。<code>@NonNull</code>将标注這個字段不應為null,初始化的時候會檢查是否為空,否則抛出<code>NullPointException</code>。在上面的無參構造函數中被忽略了。那麼,對于關注的字段标注<code>@NonNull</code>, <code>@RequiredArgsConstructor</code>則會生成帶有這些字段的構造器。
最終生成結果:
隻有<code>@NonNull</code>會生成構造器。其他預設,Java的class初始化預設為null.false,0.
lombok提供了另一種初始化做法,靜态初始化。即私有構造器,使用靜态方法建立對象。這種做法看起來簡單,但通常用的不多。因為靜态初始化的東西很難mock,對測試不夠友好。
想要初始化所有字段。
<code>@Data</code>是一個集合體。包含<code>Getter</code>,<code>Setter</code>,<code>RequiredArgsConstructor</code>,<code>ToString</code>,<code>EqualsAndHashCode</code>
這個看起來很美好,就是可以幫忙生成一個不可變對象。對于所有的字段都将生成final的。但我感覺有點失控。注解的優勢應該是所見即所得,可以通過字面量來傳遞消息。而<code>@Value</code>字段給字段加final會讓人困惑,因為這更改了我們的定義。當我想聲明一個Immutable對象的時候,我會顯示的給字段加一個限定final。
同<code>@Data</code>, <code>@Value</code>是一個集合體。包含<code>Getter</code>,<code>AllArgsConstructor</code>,<code>ToString</code>,<code>EqualsAndHashCode</code>。
編譯後
對于喜歡builder模式的人來說,聲明式簡化對象建立流程讓一切看得美好。但是,手動複制字段,手動建立方法很讓人不喜。<code>@Builder</code>解決了剛需。
這才是我們想要的建造者。對應生成的代碼為:
lombok還提供了其他幾個注解,以及還有好多内置的參數沒有講解。但是,根據2-8原理,我們根本不需要。上面這幾個足夠了。更多的注解隻會增加了解閱讀難度。
<a href="https://projectlombok.org/features/all">https://projectlombok.org/features/all</a>
<a href="http://kriszhang.com/lombok/">http://kriszhang.com/lombok/</a>
唯有不斷學習方能改變!
-- <b>Ryan Miao</b>