简介
Project Lombok是一个java库,可以自动插入编辑并构建工具,为您的java增添色彩.
永远不要再写另一个getter或equals方法,使用一个注释,您的类具有一个功能齐全的构建器,自动化您的日志记录变量等等.
实现原理
注解在编译时解析
实战
插件安装
idea插件搜索lombok
Jar包引入
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<!-- 代表编译时生效 -->
<scope>provided</scope>
</dependency>
常用注解
@Getter
为属性生成get方法
作用域:类,方法
.java文件
1 import com.sun.istack.internal.NotNull; 2 import lombok.AccessLevel; 3 import lombok.Getter; 4 5 /** 6 * @Getter注解 7 * 为属性生成get方法 8 */ 9 public class GetterTest { 10 11 @Getter( 12 /**Lazy:默认为:false,如果设置 lazy 则 该属性必须为 final*/ 13 lazy = true 14 ) 15 private final String field1 = "test"; 16 17 @Getter( 18 /**手动修改方法的访问级别*/ 19 value = AccessLevel.PRIVATE, 20 /** 21 * onMethod:默认为{},此处出现的注解会在生成的方法上面 22 * 注意版本不同写法也不同 23 * JDK7-:@Getter(onMethod=@__({@NotNull})) 24 * JDK8+:@Getter(onMethod_={@NotNull})//注意后面的下划线onMethod 25 * */ 26 onMethod_ = {@NotNull} 27 ) 28 private String field2; 29 }
反编译之后的文件
1 import com.sun.istack.internal.NotNull; 2 import java.util.concurrent.atomic.AtomicReference; 3 4 public class GetterTest { 5 private final AtomicReference<Object> field1 = new AtomicReference(); 6 private String field2; 7 8 public GetterTest() { 9 } 10 11 public String getField1() { 12 Object value = this.field1.get(); 13 if (value == null) { 14 AtomicReference var2 = this.field1; 15 synchronized(this.field1) { 16 value = this.field1.get(); 17 if (value == null) { 18 String actualValue = "test"; 19 value = "test" == null ? this.field1 : "test"; 20 this.field1.set(value); 21 } 22 } 23 } 24 25 return (String)((String)(value == this.field1 ? null : value)); 26 } 27 28 @NotNull 29 private String getField2() { 30 return this.field2; 31 } 32 }
@Setter
为属性生成set方法
作用域:类,方法
.java文件
1 import com.sun.istack.internal.NotNull; 2 import lombok.AccessLevel; 3 import lombok.Setter; 4 5 /** 6 * @Setter注解 7 * 为属性生成set方法 8 */ 9 public class SetterTest { 10 11 @Setter 12 private String field1; 13 14 @Setter( 15 /**手动修改方法的访问级别*/ 16 value = AccessLevel.PRIVATE, 17 /**该属性为参数的注解,此处可以和@NotNull 配合使用控制参数不为空,该属性配置同 onMethod*/ 18 onParam_ = {@NotNull} 19 ) 20 private String field2; 21 }
反编译之后的文件
1 import com.sun.istack.internal.NotNull; 2 3 public class SetterTest { 4 private String field1; 5 private String field2; 6 7 public SetterTest() { 8 } 9 10 public void setField1(String field1) { 11 this.field1 = field1; 12 } 13 14 private void setField2(@NotNull String field2) { 15 this.field2 = field2; 16 } 17 }
@ToString
生成toString方法
作用域:类
java文件
1 import lombok.Setter; 2 import lombok.ToString; 3 import org.junit.Test; 4 5 /** 6 * @ToString注解 7 * 生成toString方法 8 */ 9 @ToString( 10 /**在打印时包括每个字段的名称*/ 11 includeFieldNames = false, 12 /**这里列出的任何字段将不会被打印在生成的toString实现中*/ 13 // exclude = {"field1"}, 14 /** 15 * 如果存在,明确列出要打印的字段 16 * of和exclude互斥,of优先 17 */ 18 // of = {"field1"} 19 /**默认false 也就是会调用 get 方法*/ 20 doNotUseGetters = true 21 ) 22 @Setter 23 public class ToStringTest { 24 25 private String field1; 26 27 private String field2; 28 29 public String getField2(){ 30 System.out.println("调用get方法"); 31 return this.field2; 32 } 33 34 @Test 35 public void test(){ 36 ToStringTest toStringTest = new ToStringTest(); 37 toStringTest.setField1("ming"); 38 toStringTest.setField2("ting"); 39 40 System.out.println(toStringTest.toString()); 41 /** 42 * 此处不打印get方法中的 '调用get方法' 43 */ 44 //ToStringTest(ming, ting) 45 } 46 }
反编译之后的文件
1 import org.junit.Test; 2 3 public class ToStringTest { 4 private String field1; 5 private String field2; 6 7 public ToStringTest() { 8 } 9 10 public String getField2() { 11 System.out.println("调用get方法"); 12 return this.field2; 13 } 14 15 @Test 16 public void test() { 17 ToStringTest toStringTest = new ToStringTest(); 18 toStringTest.setField1("ming"); 19 toStringTest.setField2("ting"); 20 System.out.println(toStringTest.toString()); 21 } 22 23 public String toString() { 24 return "ToStringTest(" + this.field1 + ", " + this.field2 + ")"; 25 } 26 27 public void setField1(String field1) { 28 this.field1 = field1; 29 } 30 31 public void setField2(String field2) { 32 this.field2 = field2; 33 }
@EqualsAndHashCode
生成Equals和HashCode方法
作用域:类
java文件
1 import lombok.EqualsAndHashCode; 2 3 /** 4 * @EqualsAndHashCode注解 5 * 生成Equals和HashCode方法 6 */ 7 @EqualsAndHashCode( 8 exclude = {"field1"} 9 ) 10 public class EqualsAndHashCodeTest { 11 12 private String field1; 13 14 private String field2; 15 }
反编译之后的文件
1 public class EqualsAndHashCodeTest { 2 private String field1; 3 private String field2; 4 5 public EqualsAndHashCodeTest() { 6 } 7 8 public boolean equals(Object o) { 9 if (o == this) { 10 return true; 11 } else if (!(o instanceof EqualsAndHashCodeTest)) { 12 return false; 13 } else { 14 EqualsAndHashCodeTest other = (EqualsAndHashCodeTest)o; 15 if (!other.canEqual(this)) { 16 return false; 17 } else { 18 Object this$field2 = this.field2; 19 Object other$field2 = other.field2; 20 if (this$field2 == null) { 21 if (other$field2 != null) { 22 return false; 23 } 24 } else if (!this$field2.equals(other$field2)) { 25 return false; 26 } 27 28 return true; 29 } 30 } 31 } 32 33 protected boolean canEqual(Object other) { 34 return other instanceof EqualsAndHashCodeTest; 35 } 36 37 public int hashCode() { 38 int PRIME = true; 39 int result = 1; 40 Object $field2 = this.field2; 41 int result = result * 59 + ($field2 == null ? 43 : $field2.hashCode()); 42 return result; 43 } 44 }
@Data
大而全的注解:包含@Setter, @Getter, @ToString, @EqualsAndHashCode
作用域:类
java文件
1 import lombok.Data; 2 3 /** 4 * @Data注解 5 * 大而全的注解:包含@Setter, @Getter, @ToString, @EqualsAndHashCode 6 */ 7 @Data 8 public class DataTest { 9 10 private String field1; 11 12 private String field2; 13 }
反编译之后的文件
1 public class DataTest { 2 private String field1; 3 private String field2; 4 5 public DataTest() { 6 } 7 8 public String getField1() { 9 return this.field1; 10 } 11 12 public String getField2() { 13 return this.field2; 14 } 15 16 public void setField1(String field1) { 17 this.field1 = field1; 18 } 19 20 public void setField2(String field2) { 21 this.field2 = field2; 22 } 23 24 public boolean equals(Object o) { 25 if (o == this) { 26 return true; 27 } else if (!(o instanceof DataTest)) { 28 return false; 29 } else { 30 DataTest other = (DataTest)o; 31 if (!other.canEqual(this)) { 32 return false; 33 } else { 34 Object this$field1 = this.getField1(); 35 Object other$field1 = other.getField1(); 36 if (this$field1 == null) { 37 if (other$field1 != null) { 38 return false; 39 } 40 } else if (!this$field1.equals(other$field1)) { 41 return false; 42 } 43 44 Object this$field2 = this.getField2(); 45 Object other$field2 = other.getField2(); 46 if (this$field2 == null) { 47 if (other$field2 != null) { 48 return false; 49 } 50 } else if (!this$field2.equals(other$field2)) { 51 return false; 52 } 53 54 return true; 55 } 56 } 57 } 58 59 protected boolean canEqual(Object other) { 60 return other instanceof DataTest; 61 } 62 63 public int hashCode() { 64 int PRIME = true; 65 int result = 1; 66 Object $field1 = this.getField1(); 67 int result = result * 59 + ($field1 == null ? 43 : $field1.hashCode()); 68 Object $field2 = this.getField2(); 69 result = result * 59 + ($field2 == null ? 43 : $field2.hashCode()); 70 return result; 71 } 72 73 public String toString() { 74 return "DataTest(field1=" + this.getField1() + ", field2=" + this.getField2() + ")"; 75 } 76 }
val
弱语言变量
弱语言变量类型
java文件
1 import lombok.val; 2 3 import java.util.ArrayList; 4 5 /** 6 * val注解 7 * 弱语言变量 8 */ 9 public class ValTest { 10 11 public ValTest() { 12 val field = "ming"; 13 14 val list = new ArrayList<String>(); 15 list.add("ting"); 16 } 17 }
反编译之后的文件
1 import java.util.ArrayList; 2 3 public class ValTest { 4 public ValTest() { 5 String field = "ming"; 6 ArrayList<String> list = new ArrayList(); 7 list.add("ting"); 8 } 9 }
@NonNull
生成非空检查
作用在参数上
java文件
1 import lombok.NonNull; 2 3 /** 4 * @NonNull检查 5 * 生成非空检查 6 */ 7 public class NonNullTest { 8 9 public NonNullTest(@NonNull String field) { 10 System.out.println(field); 11 } 12 }
反编译之后的文件
1 import lombok.NonNull; 2 3 public class NonNullTest { 4 public NonNullTest(@NonNull String field) { 5 if (field == null) { 6 throw new NullPointerException("field is marked non-null but is null"); 7 } else { 8 System.out.println(field); 9 } 10 } 11 }
@Constructor
生成构造器
作用域:类
java文件
1 import lombok.NonNull; 2 import lombok.RequiredArgsConstructor; 3 4 /** 5 *@AllArgsConstructor 6 * @NoArgsConstructor 7 * @RequiredArgsConstructor 8 */ 9 @RequiredArgsConstructor 10 public class ConstructorTest { 11 12 private final String field1; 13 14 @NonNull 15 private String field2; 16 17 private String field3; 18 }
反编译文件
1 import lombok.NonNull; 2 3 public class ConstructorTest { 4 private final String field1; 5 @NonNull 6 private String field2; 7 private String field3; 8 9 public ConstructorTest(String field1, @NonNull String field2) { 10 if (field2 == null) { 11 throw new NullPointerException("field2 is marked non-null but is null"); 12 } else { 13 this.field1 = field1; 14 this.field2 = field2; 15 } 16 } 17 }
@CleanUp
资源关闭
Java文件
1 import lombok.Cleanup; 2 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 6 /** 7 * @CleanUp注解 8 * 资源关闭 9 */ 10 public class CleanUpTest { 11 12 public void copyFile(String in, String out) throws Exception { 13 14 @Cleanup FileInputStream fileInputStream = new FileInputStream(in); 15 @Cleanup FileOutputStream fileOutputStream = new FileOutputStream(out); 16 17 int r; 18 19 while((r = fileInputStream.read()) != -1) { 20 fileOutputStream.write(r); 21 } 22 } 23 }
反编译之后的文件
1 import java.io.FileInputStream; 2 import java.io.FileOutputStream; 3 import java.util.Collections; 4 5 public class CleanUpTest { 6 public CleanUpTest() { 7 } 8 9 public void copyFile(String in, String out) throws Exception { 10 FileInputStream fileInputStream = new FileInputStream(in); 11 12 try { 13 FileOutputStream fileOutputStream = new FileOutputStream(out); 14 15 int r; 16 try { 17 while((r = fileInputStream.read()) != -1) { 18 fileOutputStream.write(r); 19 } 20 } finally { 21 if (Collections.singletonList(fileOutputStream).get(0) != null) { 22 fileOutputStream.close(); 23 } 24 25 } 26 } finally { 27 if (Collections.singletonList(fileInputStream).get(0) != null) { 28 fileInputStream.close(); 29 } 30 31 } 32 33 } 34 }
@Slf4j
日志注解
作用域:类
Java文件
1 import lombok.extern.slf4j.Slf4j; 2 import org.junit.Test; 3 4 /** 5 *打印日志 6 */ 7 @Slf4j 8 public class LogTest { 9 10 @Test 11 public void func(){ 12 log.error("打印日志"); 13 } 14 }
@Builder和@Singular
1 import com.alibaba.fastjson.JSON; 2 import lombok.Builder; 3 import lombok.Getter; 4 import lombok.Singular; 5 6 import java.util.List; 7 8 /** 9 * 类名称:BuilderTest 10 * ******************************** 11 * <p> 12 * 类描述:@Builder和@Singular注解 13 * 14 * TODO 总结一下 15 * @Builder注解帮助我们完成的工作: 16 * 1. 一个名为XxxBuilder的内部静态类,成为构建器 17 * 2. 构建器中,对于目标类的所有属性和未初始化的final字段,都会在构建器中创建对应的属性 18 * 3. 构建器中,对每个属性都会创建一个同名的方法,用于为此属性赋值。并且支持链式调用 19 * 4. 构建器中,build方法会根据设置的属性值来创建实体对象 20 * 5. 实体类中,生成所有属性和未初始化的final字段的构造方法 21 * 6. 实体类中,会创建builder方法,用来生成构建器 22 * 23 * @Singular注解帮助我们完成的工作: 24 * 1. 构建器中,生成一个向集合添加单个元素的方法 25 * 2. 构建器中,生成一个向集合添加另一个集合的方法 26 * 3. 构建器中,生成一个清除集合元素的方法 27 * 4. build方法创建集合时,将根据集合元素多少创建不同的集合,并且创建的集合都是不可变的 28 * 29 */ 30 @Builder 31 @Getter 32 public class BuilderTest { 33 34 /** 35 * 静态属性:不能赋值的 36 */ 37 private static String staticField; 38 39 /** 40 * final属性 41 */ 42 private final String finalField; 43 44 /** 45 * 已初始化的Final字段:不能赋值的 46 */ 47 private final String initFinalField = "已初始化的Final字段!"; 48 49 /** 50 * 普通属性 51 */ 52 private String field = "普通属性Field!"; 53 54 /** 55 * 集合类属性 56 */ 57 @Singular 58 private List<String> listFields; 59 60 /** 61 * main 62 * @param args 63 */ 64 public static void main(String[] args) { 65 BuilderTest builderTest = BuilderTest 66 67 // builder创建一个可以链式赋值的对象 68 .builder() 69 70 // 为这个对象的"每个"字段赋值 71 .finalField("手动赋值FinalField字段") 72 // .field("手动赋值Field字段") 73 // .listFields(new ArrayList<>()) 74 .listField("zhangxiaoxi") 75 .listField("lisi") 76 77 // build方法来创建对象。 78 // TODO 完成了对象的创建。此时创建出来的对象,是不可变的!!! 79 .build(); 80 81 System.out.println( 82 JSON.toJSONString(builderTest, true)); 83 } 84 85 }