簡介
其他網址
官網地址:https://www.projectlombok.org/
gitbub網址:https://github.com/rzwitserloot/lombok
Automatic Resource Management, automatic generation of getters, setters, equals, hashCode and toString, and more!
在項目使用了Lombok的情況下,安裝lombok插件可以保證開發時的代碼提示和代碼檢查的正常。
Lombok能以簡單的註解形式來簡化java代碼,提高開發人員的開發效率。Lombok能通過註解的方式,在編譯時自動爲屬性生成構造器、getter/setter、equals、hashcode、toString方法。在源碼中沒有getter和setter方法,但是在編譯生成的字節碼文件中有getter和setter方法。
當修改/增加屬性時,往往需要修改toString(),getter/setter等,容易遺漏。Lombok可以自動生成。
插件安裝
1.引入依賴
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
<scope>provided</scope>
</dependency>
2.IDE支持(本處以Idea爲例)
File=>Settings=> Plugins=> 搜索“Lombok”並安裝
File=>Settings=>Compiler,Execution,Deployment=> Compiler=> AnnocationProcessors=> 選中模塊
=> Enable annocation processor
Lombok實現原理
自從Java 6起,javac就支持“JSR 269 Pluggable Annotation Processing API”規範,只要程序實現了該API,就能在javac運行的時候得到調用。
Lombok就是一個實現了"JSR 269 API"的程序。在使用javac的過程中,它產生作用的具體流程如下:
1. javac對源代碼進行分析,生成一棵抽象語法樹(AST)
2. javac編譯過程中調用實現了JSR 269的Lombok程序
3. 此時Lombok就對第一步驟得到的AST進行處理,找到Lombok註解所在類對應的語法樹 (AST),然後修改該語法樹(AST),增加Lombok註解定義的相應樹節點
4. javac使用修改後的抽象語法樹(AST)生成字節碼文件
用法
其他網址
簡介
@Getter/@Setter:
作用類上,生成所有成員變量的getter/setter方法;作用於成員變量上,生成該成員變量的getter/setter方法。可以設定訪問權限及是否懶加載等。例:@Getter(AccessLevel.PROTECTED)也可寫爲@Getter(value=AccessLevel.PROTECTED)
@ToString
作用於類,覆蓋默認的toString()方法,可以通過of屬性限定顯示某些字段,通過exclude屬性排除某些字段。
@EqualsAndHashCode
作用於類,覆蓋默認的equals和hashCode
@NonNull
主要作用於成員變量和參數中,標識不能爲空,否則拋出空指針異常。
@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor
作用於類上,用於生成構造函數。有staticName、access等屬性。staticName屬性一旦設定,將採用靜態方法的方式生成實例,access屬性可以限定訪問權限。
@NoArgsConstructor:生成無參構造器;
@RequiredArgsConstructor:生成包含final和@NonNull註解的成員變量的構造器;
@AllArgsConstructor:生成全參構造器
@Data
作用於類上,是以下註解的集合:@ToString @EqualsAndHashCode @Getter @Setter @RequiredArgsConstructor
@Builder
作用於類上,將類轉變爲建造者模式
@Log
作用於類上,生成日誌變量。針對不同的日誌實現產品,有不同的註解
@Cleanup
自動關閉資源,針對實現了java.io.Closeable接口的對象有效
@SneakyThrows
可以對受檢異常進行捕捉並拋出
引入依賴
首先引入lombok依賴
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
<scope>provided</scope>
</dependency>
1. @Getter/@Setter
爲字段生成Getter和Setter方法,可以註解到字段或者類上(註解在類上會爲類中的所有字段生成Getter和Setter方法),默認是public類型的,如果需要的話可以修改方法的訪問級別。
public class User {
@Getter @Setter
private Long id;
@Getter(AccessLevel.PROTECTED)
private String phone;
private String password;
}
編譯後的代碼:
public class User {
private Long id;
private String phone;
private String password;
public User() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
protected String getPhone() {
return this.phone;
}
}
結果解釋:
id字段生成了Getter&Setter,訪問修飾符是public(默認的)
phone只生成了Getter方法,因爲只使用了@Getter而沒有使用@Setter, 並且訪問修飾符是protected
password 上並沒有註解,所以什麼都不生成
注意:Lombok中的註解一般都會包含一個無參構造函數註解@NoArgsConstructor(用於生成無參構造函數的) ,所以還會額外生成一個無參構造函數
@Getter @Setter 註解在類上,表示爲類中的所有字段生成Getter&Setter方法。
@Getter @Setter
public class User {
private Long id;
private String phone;
private String password;
}
public class User {
private Long id;
private String phone;
private String password;
public User() {
}
public Long getId() {
return this.id;
}
public String getPhone() {
return this.phone;
}
public String getPassword() {
return this.password;
}
public void setId(Long id) {
this.id = id;
}
public void setPhone(String phone) {
this.phone = phone;
}
public void setPassword(String password) {
this.password = password;
}
}
2. @NonNull
爲字段賦值時(即調用字段的setter方法時),如果傳的參數爲null,則會拋出空異常NullPointerException,生成setter方法時會對參數是否爲空檢查。
@Getter
@Setter
public class User {
private Long id;
@NonNull
private String phone;
}
public class User {
private Long id;
@NonNull
private String phone;
public User() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
@NonNull
public String getPhone() {
return this.phone;
}
public void setPhone(@NonNull String phone) {
if(phone == null) {
throw new NullPointerException("phone");
} else {
this.phone = phone;
}
}
}
3. @NoArgsConstructor
生成一個無參構造方法。當類中有final字段沒有被初始化時,編譯器會報錯,此時可用@NoArgsConstructor(force = true),會爲沒有初始化的final字段設置默認值 0 / false / null, 這樣編譯器就不會報錯。對於具有約束的字段(例如@NonNull字段),不會生成檢查或分配,因此請注意,正確初始化這些字段之前,這些約束無效。
@NoArgsConstructor(force = true)
public class User {
private Long id;
@NonNull
private String phone;
private final Integer age;
}
public class User {
private Long id;
@NonNull
private String phone;
private final Integer age = null;
public User() {
}
}
4. @RequiredArgsConstructor
生成構造方法(可能帶參數也可能不帶參數),如果帶參數,這參數只能是以final修飾的未經初始化的字段,或者是以@NonNull註解的未經初始化的字段。
@RequiredArgsConstructor(staticName = “of”)會生成一個of()的靜態方法,並把構造方法設置爲私有的
@RequiredArgsConstructor
public class User {
private Long id;
@NonNull
private String phone;
@NotNull
private Integer status = 0;
private final Integer age;
private final String country = "china";
}
public class User {
private Long id;
@NonNull
private String phone;
@NotNull
private Integer status = Integer.valueOf(0);
private final Integer age;
private final String country = "china";
public User(@NonNull String phone, Integer age) {
if(phone == null) {
throw new NullPointerException("phone");
} else {
this.phone = phone;
this.age = age;
}
}
}
必要的構造函數只會生成final修飾的未經初始化的字段或者是以@NonNull註解的未經初始化的字段, 所以生成了public User(@NonNull String phone, Integer age)構造函數。
@RequiredArgsConstructor(staticName = "of")
public class User {
private Long id;
@NonNull
private String phone;
@NotNull
private Integer status = 0;
private final Integer age;
private final String country = "china";
}
public class User {
private Long id;
@NonNull
private String phone;
@NotNull
private Integer status = Integer.valueOf(0);
private final Integer age;
private final String country = "china";
private User(@NonNull String phone, Integer age) {
if(phone == null) {
throw new NullPointerException("phone");
} else {
this.phone = phone;
this.age = age;
}
}
public static User of(@NonNull String phone, Integer age) {
return new User(phone, age);
}
}
5. @AllArgsConstructor
生成一個全參數的構造方法
@AllArgsConstructor
public class User {
private Long id;
@NonNull
private String phone;
@NotNull
private Integer status = 0;
private final Integer age;
private final String country = "china";
}
public class User {
private Long id;
@NonNull
private String phone;
@NotNull
private Integer status = Integer.valueOf(0);
private final Integer age;
private final String country = "china";
public User(Long id, @NonNull String phone, Integer status, Integer age) {
if(phone == null) {
throw new NullPointerException("phone");
} else {
this.id = id;
this.phone = phone;
this.status = status;
this.age = age;
}
}
}
6. @ToString
生成toString()方法,默認情況下它會按順序(以逗號分隔)打印你的類名稱以及每個字段。可以這樣設置不包含哪些字段,可以指定一個也可以指定多個@ToString(exclude = “id”) / @ToString(exclude = {“id”,“name”})
如果繼承的有父類的話,可以設置callSuper 讓其調用父類的toString()方法,例如:@ToString(callSuper = true)
@ToString(exclude = {"password", "salt"})
public class User {
private Long id;
private String phone;
private String password;
private String salt;
}
public class User {
private Long id;
private String phone;
private String password;
private String salt;
public User() {
}
public String toString() {
return "User(id=" + this.id + ", phone=" + this.phone + ")";
}
}
@ToString(exclude = {"password", "salt"}, callSuper = true)
public class User {
private Long id;
private String phone;
private String password;
private String salt;
}
public class User {
private Long id;
private String phone;
private String password;
private String salt;
public User() {
}
public String toString() {
return "User(super=" + super.toString() + ", id=" + this.id + ", phone=" + this.phone + ")";
}
}
7. @EqualsAndHashCode
生成hashCode()和equals()方法,默認情況下,它將使用所有非靜態,非transient字段。但可以通過在可選的exclude參數中來排除更多字段。或者,通過在of參數中命名它們來準確指定希望使用哪些字段。
// exclude 排除字段
@EqualsAndHashCode(exclude = {“password”, “salt”})
// of 指定要包含的字段
@EqualsAndHashCode(of = {“id”, “phone”, “password”})
@EqualsAndHashCode
public class User implements Serializable{
private static final long serialVersionUID = 6569081236403751407L;
private Long id;
private String phone;
private transient int status;
}
public class User implements Serializable {
private static final long serialVersionUID = 6569081236403751407L;
private Long id;
private String phone;
private transient int status;
public User() {
}
public boolean equals(Object o) {
if(o == this) {
return true;
} else if(!(o instanceof User)) {
return false;
} else {
User other = (User)o;
if(!other.canEqual(this)) {
return false;
} else {
Long this$id = this.id;
Long other$id = other.id;
if(this$id == null) {
if(other$id != null) {
return false;
}
} else if(!this$id.equals(other$id)) {
return false;
}
String this$phone = this.phone;
String other$phone = other.phone;
if(this$phone == null) {
if(other$phone != null) {
return false;
}
} else if(!this$phone.equals(other$phone)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(Object other) {
return other instanceof User;
}
public int hashCode() {
boolean PRIME = true;
byte result = 1;
Long $id = this.id;
int result1 = result * 59 + ($id == null?43:$id.hashCode());
String $phone = this.phone;
result1 = result1 * 59 + ($phone == null?43:$phone.hashCode());
return result1;
}
}
生成了 equals 、hashCode 和 canEqual 無參構造函數 四個方法
8. @Data
@Data 包含了 @ToString、@EqualsAndHashCode、@Getter / @Setter和@RequiredArgsConstructor的功能。
@Data
public class User {
private Long id;
private String phone;
private Integer status;
}
public class User {
private Long id;
private String phone;
private Integer status;
public User() {
}
public Long getId() {
return this.id;
}
public String getPhone() {
return this.phone;
}
public Integer getStatus() {
return this.status;
}
public void setId(Long id) {
this.id = id;
}
public void setPhone(String phone) {
this.phone = phone;
}
public void setStatus(Integer status) {
this.status = status;
}
public boolean equals(Object o) {
if(o == this) {
return true;
} else if(!(o instanceof User)) {
return false;
} else {
User other = (User)o;
if(!other.canEqual(this)) {
return false;
} else {
label47: {
Long this$id = this.getId();
Long other$id = other.getId();
if(this$id == null) {
if(other$id == null) {
break label47;
}
} else if(this$id.equals(other$id)) {
break label47;
}
return false;
}
String this$phone = this.getPhone();
String other$phone = other.getPhone();
if(this$phone == null) {
if(other$phone != null) {
return false;
}
} else if(!this$phone.equals(other$phone)) {
return false;
}
Integer this$status = this.getStatus();
Integer other$status = other.getStatus();
if(this$status == null) {
if(other$status != null) {
return false;
}
} else if(!this$status.equals(other$status)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(Object other) {
return other instanceof User;
}
public int hashCode() {
boolean PRIME = true;
byte result = 1;
Long $id = this.getId();
int result1 = result * 59 + ($id == null?43:$id.hashCode());
String $phone = this.getPhone();
result1 = result1 * 59 + ($phone == null?43:$phone.hashCode());
Integer $status = this.getStatus();
result1 = result1 * 59 + ($status == null?43:$status.hashCode());
return result1;
}
public String toString() {
return "User(id=" + this.getId() + ", phone=" + this.getPhone() + ", status=" + this.getStatus() + ")";
}
}
9. @Value
@Value 將字段都變成不可變類型:使用final修飾, 同時還包含@ToString、@EqualsAndHashCode、@AllArgsConstructor 、@Getter(注意只有Getter沒有Setter)
@Value
public class User {
private Long id;
private String username;
}
public final class User {
private final Long id;
private final String username;
public User(Long id, String username) {
this.id = id;
this.username = username;
}
public Long getId() {
return this.id;
}
public String getUsername() {
return this.username;
}
public boolean equals(Object o) {
if(o == this) {
return true;
} else if(!(o instanceof User)) {
return false;
} else {
User other = (User)o;
Long this$id = this.getId();
Long other$id = other.getId();
if(this$id == null) {
if(other$id != null) {
return false;
}
} else if(!this$id.equals(other$id)) {
return false;
}
String this$username = this.getUsername();
String other$username = other.getUsername();
if(this$username == null) {
if(other$username != null) {
return false;
}
} else if(!this$username.equals(other$username)) {
return false;
}
return true;
}
}
public int hashCode() {
boolean PRIME = true;
byte result = 1;
Long $id = this.getId();
int result1 = result * 59 + ($id == null?43:$id.hashCode());
String $username = this.getUsername();
result1 = result1 * 59 + ($username == null?43:$username.hashCode());
return result1;
}
public String toString() {
return "User(id=" + this.getId() + ", username=" + this.getUsername() + ")";
}
}
10. @Log
生成log對象,用於記錄日誌,可以通過topic屬性來設置getLogger(String name)方法的參數 例如 @Log4j(topic = “com.xxx.entity.User”),默認是類的全限定名,即 類名.class,log支持以下幾種:
@Log java.util.logging.Logger
@Log4j org.apache.log4j.Logger
@Log4j2 org.apache.logging.log4j.Logger
@Slf4j org.slf4j.Logger
@XSlf4j org.slf4j.ext.XLogger
@CommonsLog org.apache.commons.logging.Log
@JBossLog org.jboss.logging.Logger
@Log
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
@Log4j
private static final Logger log = org.apache.log4j.Logger.Logger.getLogger(UserService.class);
@Log4j2
private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
@Slf4j
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
@XSlf4j
private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);
@CommonsLog
private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);
@JBossLog
private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class);
@Log
public class UserService {
public void addUser(){
log.info("add user");
}
}
import java.util.logging.Logger;
public class UserService {
private static final Logger log = Logger.getLogger(UserService.class.getName());
public UserService() {
}
}
11. @SneakyThrows
使用try catch 來捕獲異常, 默認捕獲的是Throwable異常,也可以設置要捕獲的異常
public class User {
@SneakyThrows
public void sleep(){
Thread.sleep(1000);
}
@SneakyThrows(InterruptedException.class)
public void sleep2() {
Thread.sleep(1000);
}
}
public class User {
public User() {
}
public void sleep() {
try {
Thread.sleep(1000L);
} catch (Throwable var2) {
throw var2;
}
}
public void sleep2() {
try {
Thread.sleep(1000L);
} catch (InterruptedException var2) {
throw var2;
}
}
public static void main(String[] args) {
}
}
12. @Synchronized
給方法加上同步鎖
public class User {
private final Object readLock = new Object();
@Synchronized
public static void foo(){
System.out.println();
}
@Synchronized
public void bar(){
System.out.println();
}
@Synchronized("readLock")
public void test() {
System.out.println();
}
}
public class User {
private static final Object $LOCK = new Object[0];
private final Object $lock = new Object[0];
private final Object readLock = new Object();
public User() {
}
public static void foo() {
Object var0 = $LOCK;
synchronized($LOCK) {
System.out.println();
}
}
public void bar() {
Object var1 = this.$lock;
synchronized(this.$lock) {
System.out.println();
}
}
public void test() {
Object var1 = this.readLock;
synchronized(this.readLock) {
System.out.println();
}
}
}
13. @Cleanup
主要用來修飾 IO 流相關類, 會在 finally 代碼塊中對該資源進行 close();
public class CleanupExample {
public static void main(String[] args) throws IOException {
@Cleanup InputStream in = new FileInputStream(args[0]);
@Cleanup OutputStream out = new FileOutputStream(args[1]);
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
}
}
public class CleanupExample {
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream(args[0]);
try {
OutputStream out = new FileOutputStream(args[1]);
try {
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
} finally {
if (out != null) {
out.close();
}
}
} finally {
if (in != null) {
in.close();
}
}
}
}
14. @Getter(lazy = true)
@Getter(lazy = true)
標註字段爲懶加載字段,懶加載字段在創建對象時不會進行初始化,而是在第一次訪問的時候纔會初始化,後面再次訪問也不會重複初始化。
public class User {
private final List<String> cityList = getCityFromCache();
private List<String> getCityFromCache() {
System.out.println("get city from cache ...");
return new ArrayList<>();
}
}
public static void main(String[] args) {
User user = new User(); // 初始化對象時會執行getCityFromCache()方法
}
public class User {
@Getter(lazy = true)
private final List<String> cityList = getCityFromCache();
private List<String> getCityFromCache() {
System.out.println("get city from cache ...");
return new ArrayList<>();
}
}
public class User {
private final AtomicReference<Object> cityList = new AtomicReference();
public User() {
}
private List<String> getCityFromCache() {
System.out.println("get city from cache ...");
return new ArrayList();
}
public List<String> getCityList() {
Object value = this.cityList.get();
if(value == null) {
AtomicReference var2 = this.cityList;
synchronized(this.cityList) {
value = this.cityList.get();
if(value == null) {
List actualValue = this.getCityFromCache();
value = actualValue == null?this.cityList:actualValue;
this.cityList.set(value);
}
}
}
return (List)((List)(value == this.cityList?null:value));
}
}
@Getter(lazy = true):爲懶加載字段生成一個Getter方法
public static void main(String[] args) {
User user = new User(); // 創建對象時不會初始化懶加載的字段
List<String> cityList = user.getCityList(); // 只有第一次訪問屬性時纔會去初始化
cityList = user.getCityList(); // 第二次就不會再次初始化了
}
15. @Wither
提供了給final字段賦值的一種方法
public class User {
@Wither
private final String country;
public User(String country) {
this.country = country;
}
}
public class User {
private final String country;
public User(String country) {
this.country = country;
}
public User withCountry(String country) {
return this.country == country?this:new User(country);
}
}
16. @Builder
@Builder註釋爲你的類生成複雜的構建器API。
@Builder
public class User {
private Long id;
private String phone;
}
public class User {
private Long id;
private String phone;
User(Long id, String phone) {
this.id = id;
this.phone = phone;
}
public static User.UserBuilder builder() {
return new User.UserBuilder();
}
public static class UserBuilder {
private Long id;
private String phone;
UserBuilder() {
}
public User.UserBuilder id(Long id) {
this.id = id;
return this;
}
public User.UserBuilder phone(String phone) {
this.phone = phone;
return this;
}
public User build() {
return new User(this.id, this.phone);
}
public String toString() {
return "User.UserBuilder(id=" + this.id + ", phone=" + this.phone + ")";
}
}
}
17. @Delegate
爲List類型的字段生成一大堆常用的方法,其實這些方法都是List中的方法
注意:一個類中只能使用一個@Delegate註解,因爲使用多個會生成多個size()方法,從而會編譯報錯。
public class User {
@Delegate
private List<String> address;
}
public class User {
private List<String> address;
public User() {
}
public int size() {
return this.address.size();
}
public boolean isEmpty() {
return this.address.isEmpty();
}
public boolean contains(Object arg0) {
return this.address.contains(arg0);
}
public Iterator<String> iterator() {
return this.address.iterator();
}
public Object[] toArray() {
return this.address.toArray();
}
public <T> T[] toArray(T[] arg0) {
return this.address.toArray(arg0);
}
public boolean add(String arg0) {
return this.address.add(arg0);
}
public boolean remove(Object arg0) {
return this.address.remove(arg0);
}
public boolean containsAll(Collection<?> arg0) {
return this.address.containsAll(arg0);
}
public boolean addAll(Collection<? extends String> arg0) {
return this.address.addAll(arg0);
}
public boolean addAll(int arg0, Collection<? extends String> arg1) {
return this.address.addAll(arg0, arg1);
}
public boolean removeAll(Collection<?> arg0) {
return this.address.removeAll(arg0);
}
public boolean retainAll(Collection<?> arg0) {
return this.address.retainAll(arg0);
}
public void replaceAll(UnaryOperator<String> arg0) {
this.address.replaceAll(arg0);
}
public void sort(Comparator<? super String> arg0) {
this.address.sort(arg0);
}
public void clear() {
this.address.clear();
}
public String get(int arg0) {
return (String)this.address.get(arg0);
}
public String set(int arg0, String arg1) {
return (String)this.address.set(arg0, arg1);
}
public void add(int arg0, String arg1) {
this.address.add(arg0, arg1);
}
public String remove(int arg0) {
return (String)this.address.remove(arg0);
}
public int indexOf(Object arg0) {
return this.address.indexOf(arg0);
}
public int lastIndexOf(Object arg0) {
return this.address.lastIndexOf(arg0);
}
public ListIterator<String> listIterator() {
return this.address.listIterator();
}
public ListIterator<String> listIterator(int arg0) {
return this.address.listIterator(arg0);
}
public List<String> subList(int arg0, int arg1) {
return this.address.subList(arg0, arg1);
}
public Spliterator<String> spliterator() {
return this.address.spliterator();
}
}
lombok.config
lombok.config配置文件是通過一些設置來控制代碼生成的規則或者稱之爲習慣,配置文件的位置應放在src/mian/java,不要放置在src/main/resources。
注意配置文件和要使用註解的類要在同一套代碼中,要麼同時在src/main/java 要麼同時在 src/test/java中
lombok.config
#lombok 默認對boolean類型字段生成的get方法使用is前綴, 通過此配置則使用get前綴,默認: false
lombok.getter.noIsPrefix=true
#默認的set方法返回void設置爲true返回調用對象本身,這樣方便使用鏈式來繼續調用方法,默認: false
lombok.accessors.chain=true
#如果設置爲true get和set方法將不帶get,set前綴, 直接以字段名爲方法名, 默認: false
lombok.accessors.fluent=true
#設置log類註解返回的字段名稱,默認: log
lombok.log.fieldName=logger
@Log4j
@Getter @Setter
public class User {
private String username;
private boolean vip;
private boolean isOldUser;
}
public class User {
private static final Logger logger = Logger.getLogger(User.class);
private String username;
private boolean vip;
private boolean isOldUser;
public User() {
}
public String username() {
return this.username;
}
public boolean vip() {
return this.vip;
}
public boolean isOldUser() {
return this.isOldUser;
}
public User username(String username) {
this.username = username;
return this;
}
public User vip(boolean vip) {
this.vip = vip;
return this;
}
public User isOldUser(boolean isOldUser) {
this.isOldUser = isOldUser;
return this;
}
}