一. 為什麼要用@Accessors?
通常,在建立對象的時候,我們使用構造函數為成員變量指派。一個對象的初始化,參數有時候不固定,是以就有了參數不同的構造函數。但是,如果一個類的成員變量很多,那麼就有可能産生很多的構造函數。當然,你可以使用無參的構造函數先建立一個對象,再去調用setter方法為需要初始化的變量指派。這樣做的弊端很明顯,就是一行行的setter方法費時費力。不然,也不會有不同的構造函數。但是,即使有了很多不同的構造函數,對于建立一個複雜的對象(擁有很多成員變量)也很棘手。因為在new的過程中,當我們傳入構造函數的參數很多,會出現這樣一種情況——不知道這個參數具體是幹什麼的。這時候構造函數,似乎不如setter方法那樣清晰明了,因為setter方法名可以幫助我們了解這個參數具體的作用。
那麼有沒有辦法,讓我們在建立對象的過程中,既能擁有多個構造函數的參數不确定的特點,同時又能夠像setter方法那樣知道每個參數具體的作用呢?其實這就是我們常說的建造者模式,在《Lombok之@Builder使用》中,我們知道了@Builder可以實作這樣的功能。不過,它也有點缺陷——無法在建立對象後繼續使用鍊式指派。幸運的是,Lombok出了一個@Accessors注解,完美地解決了這個問題,它可以讓你随時随地使用鍊式指派。
二. @Accessors如何使用?
在@Accessors的官方文檔中,對于@Accessors的總結是——A more fluent API for getters and setters.意為:面向getter和setter的更流暢的API。是以,@Accessors是配合@Getter/@Setter注解一起使用的。代碼如下:
@Getter
@Setter
@Accessors(fluent = true, chain = true)
public class Student {
private String name;
private Integer age;
}
反編譯後的代碼如下:
public class Student {
private String name;
private Integer age;
public Student() {
}
public String name() {
return this.name;
}
public Integer age() {
return this.age;
}
public Student name(String name) {
this.name = name;
return this;
}
public Student age(Integer age) {
this.age = age;
return this;
}
}
可以看到,所有的getter和setter方法都使用了變量名的作為方法名。setter方法的傳回值全是Student類型。代碼示範:
三. @Accessors源碼
package lombok.experimental;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* A container for settings for the generation of getters and setters.
* <p>
* Complete documentation is found at <a href="https://projectlombok.org/features/experimental/Accessors" target="_blank" rel="external nofollow" >the project lombok features page for @Accessors</a>.
* <p>
* Using this annotation does nothing by itself; an annotation that makes lombok generate getters and setters,
* such as {@link lombok.Setter} or {@link lombok.Data} is also required.
*/
@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.SOURCE)
public @interface Accessors {
/**
* If true, accessors will be named after the field and not include a {@code get} or {@code set}
* prefix. If true and {@code chain} is omitted, {@code chain} defaults to {@code true}.
* <strong>default: false</strong>
*
* @return Whether or not to make fluent methods (named {@code fieldName()}, not for example {@code setFieldName}).
*/
boolean fluent() default false;
/**
* If true, setters return {@code this} instead of {@code void}.
* <strong>default: false</strong>, unless {@code fluent=true}, then <strong>default: true</strong>
*
* @return Whether or not setters should return themselves (chaining) or {@code void} (no chaining).
*/
boolean chain() default false;
/**
* If present, only fields with any of the stated prefixes are given the getter/setter treatment.
* Note that a prefix only counts if the next character is NOT a lowercase character or the last
* letter of the prefix is not a letter (for instance an underscore). If multiple fields
* all turn into the same name when the prefix is stripped, an error will be generated.
*
* @return If you are in the habit of prefixing your fields (for example, you name them {@code fFieldName}, specify such prefixes here).
*/
String[] prefix() default {};
}
- 元注解:@Target({ElementType.TYPE, ElementType.FIELD}),@Retention(RetentionPolicy.SOURCE)
-
注解屬性:fluent注解預設值為false,則保留getter和setter方法前面的get和set字首。如果為true,則不保留字首,直接使用變量名作為方法名,也就構成了方法的重載。
值得注意的是,當fluent為true時,chain注解屬性的值就自動設定成了true。chain的預設值是false,意味不啟用鍊式指派,也就是setter方法傳回體為void。
prefix注解屬性處理變量名字首的,隻有擁有字首的變量才會生成getter/setter方法,而且它的比對原則是——比對到的變量去掉字首後第一個字母不能是小寫。通俗地說就是,運用駝峰命名規則去比對。
四. 特别說明
本文已經收錄在Lombok注解系列文章總覽中,并繼承上文中所提的特别說明。
源碼位址:gitee