Lombok
Lombok 是一种 Java 实用工具,可用来帮助开发人员消除 Java 的冗长,尤其是对于简单的 Java 对象(POJO)。它通过注释实现这一目的。通过在开发环境中实现 Lombok,开发人员可以节省构建诸如 hashCode()
和 equals()
、getter / setter
这样的方法以及以往用来分类各种 accessor 和 mutator 的大量时间。
Lombok 安装
使 IntelliJ IDEA 支持 Lombok 方式如下:
-
Intellij 设置支持注解处理
点击 File > Settings > Build > Annotation Processors
勾选 Enable annotation processing
-
安装插件
点击 Settings > Plugins > Browse repositories
查找 Lombok Plugin 并进行安装
重启 IntelliJ IDEA
-
将 lombok 添加到 pom 文件
1 2 3 4 5 6 7 | <!-- https: //mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version> 1.18 . 6 </version> <scope>provided</scope> </dependency> |
Lombok 使用
官网API
Lombok 提供注解API 来修饰指定的类:
@Getter and @Setter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | @Getter and @Setter Lombok 代码: @Getter @Setter private boolean employed = true ; @Setter (AccessLevel.PROTECTED) private String name; 等价于 Java 源码: private boolean employed = true ; private String name; public boolean isEmployed() { return employed; } public void setEmployed( final boolean employed) { this .employed = employed; } protected void setName( final String name) { this .name = name; } |
@NonNull
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | @NonNull Lombok 代码: @Getter @Setter @NonNull private List<Person> members; 等价于 Java 源码: @NonNull private List<Person> members; public Family( @NonNull final List<Person> members) { if (members == null ) throw new java.lang.NullPointerException( "members" ); this .members = members; } @NonNull public List<Person> getMembers() { return members; } public void setMembers( @NonNull final List<Person> members) { if (members == null ) throw new java.lang.NullPointerException( "members" ); this .members = members; } |
@ToString
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | @ToString Lombok 代码: @ToString (callSuper= true ,exclude= "someExcludedField" ) public class Foo extends Bar { private boolean someBoolean = true ; private String someStringField; private float someExcludedField; } 等价于 Java 源码: public class Foo extends Bar { private boolean someBoolean = true ; private String someStringField; private float someExcludedField; @java .lang.Override public java.lang.String toString() { return "Foo(super=" + super .toString() + ", someBoolean=" + someBoolean + ", someStringField=" + someStringField + ")" ; } } |
@EqualsAndHashCode
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | @EqualsAndHashCode Lombok 代码: @EqualsAndHashCode (callSuper= true ,exclude={ "address" , "city" , "state" , "zip" }) public class Person extends SentientBeing { enum Gender { Male, Female } @NonNull private String name; @NonNull private Gender gender; private String ssn; private String address; private String city; private String state; private String zip; } 等价于 Java 源码: public class Person extends SentientBeing { enum Gender { /*public static final*/ Male /* = new Gender() */ , /*public static final*/ Female /* = new Gender() */ ; } @NonNull private String name; @NonNull private Gender gender; private String ssn; private String address; private String city; private String state; private String zip; @java .lang.Override public boolean equals( final java.lang.Object o) { if (o == this ) return true ; if (o == null ) return false ; if (o.getClass() != this .getClass()) return false ; if (! super .equals(o)) return false ; final Person other = (Person)o; if ( this .name == null ? other.name != null : ! this .name.equals(other.name)) return false ; if ( this .gender == null ? other.gender != null : ! this .gender.equals(other.gender)) return false ; if ( this .ssn == null ? other.ssn != null : ! this .ssn.equals(other.ssn)) return false ; return true ; } @java .lang.Override public int hashCode() { final int PRIME = 31 ; int result = 1 ; result = result * PRIME + super .hashCode(); result = result * PRIME + ( this .name == null ? 0 : this .name.hashCode()); result = result * PRIME + ( this .gender == null ? 0 : this .gender.hashCode()); result = result * PRIME + ( this .ssn == null ? 0 : this .ssn.hashCode()); return result; } } |
@Data
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | @Data Lombok 代码: @Data (staticConstructor= "of" ) public class Company { private final Person founder; private String name; private List<Person> employees; } 等价于 Java 源码: public class Company { private final Person founder; private String name; private List<Person> employees; private Company( final Person founder) { this .founder = founder; } public static Company of( final Person founder) { return new Company(founder); } public Person getFounder() { return founder; } public String getName() { return name; } public void setName( final String name) { this .name = name; } public List<Person> getEmployees() { return employees; } public void setEmployees( final List<Person> employees) { this .employees = employees; } @java .lang.Override public boolean equals( final java.lang.Object o) { if (o == this ) return true ; if (o == null ) return false ; if (o.getClass() != this .getClass()) return false ; final Company other = (Company)o; if ( this .founder == null ? other.founder != null : ! this .founder.equals(other.founder)) return false ; if ( this .name == null ? other.name != null : ! this .name.equals(other.name)) return false ; if ( this .employees == null ? other.employees != null : ! this .employees.equals(other.employees)) return false ; return true ; } @java .lang.Override public int hashCode() { final int PRIME = 31 ; int result = 1 ; result = result * PRIME + ( this .founder == null ? 0 : this .founder.hashCode()); result = result * PRIME + ( this .name == null ? 0 : this .name.hashCode()); result = result * PRIME + ( this .employees == null ? 0 : this .employees.hashCode()); return result; } @java .lang.Override public java.lang.String toString() { return "Company(founder=" + founder + ", name=" + name + ", employees=" + employees + ")" ; } } 所有属性的get和set方法 toString 方法 hashCode方法 equals方法 |
@Cleanup
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | @Cleanup Lombok 代码: public void testCleanUp() { try { @Cleanup ByteArrayOutputStream baos = new ByteArrayOutputStream(); baos.write( new byte [] { 'Y' , 'e' , 's' }); System.out.println(baos.toString()); } catch (IOException e) { e.printStackTrace(); } } 等价于 Java 源码: public void testCleanUp() { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { baos.write( new byte []{ 'Y' , 'e' , 's' }); System.out.println(baos.toString()); } finally { baos.close(); } } catch (IOException e) { e.printStackTrace(); } } |
@Synchronized
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | @Synchronized Lombok 代码: private DateFormat format = new SimpleDateFormat( "MM-dd-YYYY" ); @Synchronized public String synchronizedFormat(Date date) { return format.format(date); } 等价于 Java 源码: private final java.lang.Object $lock = new java.lang.Object[ 0 ]; private DateFormat format = new SimpleDateFormat( "MM-dd-YYYY" ); public String synchronizedFormat(Date date) { synchronized ($lock) { return format.format(date); } } |
@SneakyThrows
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | @SneakyThrows Lombok 代码: @SneakyThrows public void testSneakyThrows() { throw new IllegalAccessException(); } Exception in thread "main" java.lang.IllegalAccessException at com.topcheer.springboot01.Test.main(Test.java: 15 ) 等价于 Java 源码: public void testSneakyThrows() { try { throw new IllegalAccessException(); } catch (java.lang.Throwable $ex) { throw lombok.Lombok.sneakyThrow($ex); } } java.lang.IllegalAccessException at com.topcheer.springboot01.Test.main(Test.java: 13 ) 示例 使用 Lombok 定义一个 Java Bean import lombok.Data; import lombok.ToString; @Data @ToString (exclude = "age" ) public class Person { private String name; private Integer age; private String sex; } 测试 Person person = new Person(); person.setName( "张三" ); person.setAge( 20 ); person.setSex( "男" ); System.out.println(person.toString()); // output: Person(name=张三, sex=男) |
其他说明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | @AllArgsConstructor 这个注解是所有的参数构造器 @NoArgsConstructor 无参构造 @RequiredArgsConstructor 为每个需要特殊处理的字段生成一个带有 1 个参数的构造函数,且生成的构造为私有,需要通过设置 staticName 来获取访问; @RequiredArgsConstructor 功能 生成一个包含必填参数的构造函数 注意 要与 @NonNull 搭配使用,该注解修饰的属性就是必填参数 源码 @RequiredArgsConstructor public class LombokDemo { @NonNull private Integer id; private String name; } 编译后 package xyz.mrwood.study.lombok; import java.beans.ConstructorProperties; import lombok.NonNull; public class LombokDemo { @NonNull private Integer id; private String name; @ConstructorProperties ({ "id" }) public LombokDemo( @NonNull Integer id) { if (id == null ) { throw new NullPointerException( "id" ); } else { this .id = id; } } } @NoAragsConstructor 功能 添加一个无参构造函数 注意 这个注解在没有其它有参构造函数的情况下使用意义不大,因为在这种情况下java默认会添加一个无参构造函数 源码 @NoArgsConstructor public class LombokDemo { private Integer id; private String name; } 编译后 package xyz.mrwood.study.lombok; public class LombokDemo { private Integer id; private String name; public LombokDemo() { } } @AllArgsConstructor 功能 添加一个所有参数的构造函数 源码 @AllArgsConstructor public class LombokDemo { private Integer id; private String name; } 编译后 package xyz.mrwood.study.lombok; import java.beans.ConstructorProperties; public class LombokDemo { private Integer id; private String name; @ConstructorProperties ({ "id" , "name" }) public LombokDemo(Integer id, String name) { this .id = id; this .name = name; } } |
@Value
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | @Value 功能 不可变类的 @Date , 他会默认给属性加上 final 源码 @Value public class LombokDemo { private Integer id; private String name; } 编译后 package xyz.mrwood.study.lombok; import java.beans.ConstructorProperties; public final class LombokDemo { private final Integer id; private final String name; @ConstructorProperties ({ "id" , "name" }) public LombokDemo(Integer id, String name) { this .id = id; this .name = name; } public Integer getId() { return this .id; } public String getName() { return this .name; } public boolean equals(Object o) { if (o == this ) { return true ; } else if (!(o instanceof LombokDemo)) { return false ; } else { LombokDemo other = (LombokDemo)o; Integer this $id = this .getId(); Integer 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 $name = this .getName(); String other$name = other.getName(); if ( this $name == null ) { if (other$name != null ) { return false ; } } else if (! this $name.equals(other$name)) { return false ; } return true ; } } public int hashCode() { boolean PRIME = true ; byte result = 1 ; Integer $id = this .getId(); int result1 = result * 59 + ($id == null ? 43 :$id.hashCode()); String $name = this .getName(); result1 = result1 * 59 + ($name == null ? 43 :$name.hashCode()); return result1; } public String toString() { return "LombokDemo(id=" + this .getId() + ", name=" + this .getName() + ")" ; } } |
@Builder
1 2 3 4 5 6 7 8 9 10 | 注解提供了一种比较推崇的构建值对象的方式 Dog dog = Dog.builder().age( 12 ).name( "大黄" ).build(); System.out.println(dog); //Dog(name=大黄, age=12) 但是的确很有创意,这些注解已经在jar中提供,只不过它是归在”lombok.experimental.” 包中;而基本功能在”lombok.” 包中。 @Builder .Default private Boolean flag = false ; //Dog(name=大黄, age=12, flag=false) 初始化的时候会把值带进去,适合有默认值的 |
@Accessors 定制流畅的访问器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @Accessors (chain= true ) 链式访问,该注解设置chain= true ,生成setter方法返回 this ,代替了默认的返回 void 。 package com.pollyduan; import lombok.Data; import lombok.experimental.Accessors; @Data @Accessors (chain= true ) public class User { private Integer id; private String name; private Integer age; public static void main(String[] args) { User user= new User().setAge( 31 ).setName( "pollyduan" ); System.out.println(user); } @Accessors (fluent = true ) 与chain= true 类似,区别在于getter和setter不带set和get前缀。 |
@val @var
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | 使用Lombok ,java也能够像javascript一样使用弱类型定义变量了 val注解变量申明是 final 类型 var注解变量是非 final 类型 import java.util.ArrayList; import java.util.HashMap; import lombok.val; public class ValExample { public String example() { val example = new ArrayList<String>(); example.add( "Hello, World!" ); val foo = example.get( 0 ); return foo.toLowerCase(); } public void example2() { val map = new HashMap<Integer, String>(); map.put( 0 , "zero" ); map.put( 5 , "five" ); for (val entry : map.entrySet()) { System.out.printf( "%d: %s\n" , entry.getKey(), entry.getValue()); } } } 翻译后 import java.util.ArrayList; import java.util.HashMap; import java.util.Map; public class ValExample { public String example() { final ArrayList<String> example = new ArrayList<String>(); example.add( "Hello, World!" ); final String foo = example.get( 0 ); return foo.toLowerCase(); } public void example2() { final HashMap<Integer, String> map = new HashMap<Integer, String>(); map.put( 0 , "zero" ); map.put( 5 , "five" ); for ( final Map.Entry<Integer, String> entry : map.entrySet()) { System.out.printf( "%d: %s\n" , entry.getKey(), entry.getValue()); } } } |
@UtilityClass
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 功能 把普通类转为工具类 源码 @UtilityClass public class LombokDemo { private Integer id = 1 ; private String name = "kiwi" ; public void util(){ System.out.println( "xxx" ); } } 编译后 package xyz.mrwood.study.lombok; public final class LombokDemo { private static Integer id = Integer.valueOf( 1 ); private static String name = "kiwi" ; public static void util() { System.out.println( "xxx" ); } private LombokDemo() { throw new UnsupportedOperationException( "This is a utility class and cannot be instantiated" ); } } |
资料
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步