lombok是一个编译级别的插件,它可以在项目编译的时候生成一些代码。在很多工具类的项目中都有这个功能。比如dagger。 通俗的说,lombok可以通过注解来标示生成getter
settter
等代码。我们自然可以通过编译器比如IDEA的Generate
生成,为啥要用这个?
说明 在项目开发阶段,一个class的属性是一直变化的,今天可能增加一个字段,明天可能删除一个字段。每次变化都需要修改对应的模板代码。另外,有的class的字段超级多,多到一眼看不完。如果加上模板代码,更难一眼看出来。更有甚者,由于字段太多,想要使用builder来创建。手动创建builder和字段和原来的类夹杂在一起,看起来真的难受。lombok的@Builder
即可解决这个问题。
引入 引入就是加入lombok
的jar包。
在maven中 直接加入依赖
1 2 3 4 5 <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > <version > 1.16.20</version > </dependency >
在gradle中 这里比较麻烦,需要添加一个编译时生成代码的插件。gradle里有几个这样的插件。但为了简化过程,lombok提供了新插件。
来源:官网 , github
首先,添加一个plugin
1 2 3 plugins { id 'io.franzbecker.gradle-lombok' version '1.11' }
然后,就可以了。还可以配置lombok的版本:
1 2 3 4 lombok { // optional: values below are the defaults version = "1.16.20" sha256 = "" }
IntelIJ IDEA 插件 在IDEA里使用需要添加一个插件。在插件里搜索lombok,安装,重启。
IDEA里需要在设置中启用annotation processors。
如果升级了InteliJ IDEA, 可能出现lombok不能用了,右键更新lombok plugin,重启即可。
基本用法 测试代码: https://github.com/Ryan-Miao/someTest/tree/master/src/main/java/com/test/lombok
Geter Setter 最简单的,最常用的,最直观的使用就是getter setter方法。
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 package com.test.lombok;import lombok.AccessLevel;import lombok.Getter;import lombok.Setter;import java.util.Date;public class GetterSetterExample { @Getter @Setter private int age = 10 ; @Getter @Setter private boolean active; @Getter @Setter private Boolean none; @Getter @Setter private Date date; @Setter(AccessLevel.PROTECTED) private String name; @Override public String toString () { return String.format("%s (age: %d)" , name, age); } public static void main (String[] args) { GetterSetterExample example = new GetterSetterExample (); example.setActive(true ); example.setAge(123 ); example.setDate(new Date ()); example.setName("abc" ); example.setNone(false ); Date date = example.getDate(); Boolean none = example.getNone(); boolean active = example.isActive(); } }
简单使用没有问题,深入一点可以看到有些特殊设定。比如javadoc.
Getter
声明创建getter方法;
Setter
声明创建setter方法;
@Setter(AccessLevel.PROTECTED)
可以添加参数,指定权限为私有;
Attention!关于boolean
的set前缀都是set,但getter不同,小写的boolean
,即基本类型,前缀是is
; Boolean
,即包装类型,前缀是get
;
编译后的结果如下:
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 package com.test.lombok;import java.util.Date;public class GetterSetterExample { private int age = 10 ; private boolean active; private Boolean none; private Date date; private String name; public GetterSetterExample () { } public String toString () { return String.format("%s (age: %d)" , this .name, this .age); } public static void main (String[] args) { GetterSetterExample example = new GetterSetterExample (); example.setActive(true ); example.setAge(123 ); example.setDate(new Date ()); example.setName("abc" ); example.setNone(false ); Date date = example.getDate(); Boolean none = example.getNone(); boolean active = example.isActive(); } public int getAge () { return this .age; } public void setAge (int age) { this .age = age; } public boolean isActive () { return this .active; } public void setActive (boolean active) { this .active = active; } public Boolean getNone () { return this .none; } public void setNone (Boolean none) { this .none = none; } public Date getDate () { return this .date; } public void setDate (Date date) { this .date = date; } protected void setName (String name) { this .name = name; } }
ToString 虽然ToString在生产环境貌似没什么卵用。但是,很多情况下,我们还是需要这个的。因为记log。不想每次看log的时候是一串@地址,那就好好把toString()加上。
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 package com.test.lombok;import lombok.Setter;import lombok.ToString;@Setter @ToString(exclude="id") public class ToStringExample { private static final int STATIC_VAR = 10 ; private String name; private Shape shape = new Square (5 , 10 ); private String[] tags; private int id; @ToString(callSuper=true, includeFieldNames=true) public static class Square extends Shape { private final int width, height; public Square (int width, int height) { this .width = width; this .height = height; } } @ToString public static class Shape { private int color; } public static void main (String[] args) { final ToStringExample example = new ToStringExample (); example.setId(1 ); example.setName("abc" ); example.setTags(new String []{"a" ,"b" ,"c" }); final Shape shape = new Square (1 ,2 ); example.setShape(shape); System.out.println(example.toString()); } }
1.@ToString
最简单使用即可
打印结果如下:
ToStringExample(name=abc, shape=ToStringExample.Square(super=ToStringExample.Shape(color=0), width=1, height=2), tags=[a, b, c])
编译后的代码如下:
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 package com.test.lombok;import java.util.Arrays;public class ToStringExample { private static final int STATIC_VAR = 10 ; private String name; private ToStringExample.Shape shape = new ToStringExample .Square(5 , 10 ); private String[] tags; private int id; public ToStringExample () { } public static void main (String[] args) { ToStringExample example = new ToStringExample (); example.setId(1 ); example.setName("abc" ); example.setTags(new String []{"a" , "b" , "c" }); ToStringExample.Shape shape = new ToStringExample .Square(1 , 2 ); example.setShape(shape); System.out.println(example.toString()); } public void setName (String name) { this .name = name; } public void setShape (ToStringExample.Shape shape) { this .shape = shape; } public void setTags (String[] tags) { this .tags = tags; } public void setId (int id) { this .id = id; } public String toString () { return "ToStringExample(name=" + this .name + ", shape=" + this .shape + ", tags=" + Arrays.deepToString(this .tags) + ")" ; } public static class Shape { private int color; public Shape () { } public String toString () { return "ToStringExample.Shape(color=" + this .color + ")" ; } } public static class Square extends ToStringExample .Shape { private final int width; private final int height; public Square (int width, int height) { this .width = width; this .height = height; } public String toString () { return "ToStringExample.Square(super=" + super .toString() + ", width=" + this .width + ", height=" + this .height + ")" ; } } }
@EqualsAndHashCode equals()和hashCode()在Java中有着举足轻重的基地作用,虽然通常很少关注。但是,这个必须不可省。不知道有几个可以手写出来的。
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 package com.test.lombok;import lombok.EqualsAndHashCode;@EqualsAndHashCode(exclude={"id", "shape"}) public class EqualsAndHashCodeExample { private transient int transientVar = 10 ; private String name; private double score; private ToStringExample.Shape shape = new Square (5 , 10 ); private String[] tags; private int id; public String getName () { return this .name; } @EqualsAndHashCode(callSuper=true) public static class Square extends ToStringExample .Shape { private final int width, height; public Square (int width, int height) { this .width = width; this .height = height; } } public static void main (String[] args) { EqualsAndHashCodeExample example = new EqualsAndHashCodeExample (); EqualsAndHashCodeExample example1 = new EqualsAndHashCodeExample (); boolean equals = example.equals(example1); boolean b = example.canEqual(example); int i = example.hashCode(); } }
编译后的结果为:
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 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 package com.test.lombok;import com.test.lombok.ToStringExample.Shape;import java.util.Arrays;public class EqualsAndHashCodeExample { private transient int transientVar = 10 ; private String name; private double score; private Shape shape = new EqualsAndHashCodeExample .Square(5 , 10 ); private String[] tags; private int id; public EqualsAndHashCodeExample () { } public String getName () { return this .name; } public static void main (String[] args) { EqualsAndHashCodeExample example = new EqualsAndHashCodeExample (); EqualsAndHashCodeExample example1 = new EqualsAndHashCodeExample (); example.equals(example1); boolean b = example.canEqual(example); int i = example.hashCode(); } public boolean equals (Object o) { if (o == this ) { return true ; } else if (!(o instanceof EqualsAndHashCodeExample)) { return false ; } else { EqualsAndHashCodeExample other = (EqualsAndHashCodeExample)o; if (!other.canEqual(this )) { return false ; } else { label31: { Object this$name = this .getName(); Object other$name = other.getName(); if (this $name == null ) { if (other$name == null ) { break label31; } } else if (this $name.equals(other$name)) { break label31; } return false ; } if (Double.compare(this .score, other.score) != 0 ) { return false ; } else { return Arrays.deepEquals(this .tags, other.tags); } } } } protected boolean canEqual (Object other) { return other instanceof EqualsAndHashCodeExample; } public int hashCode () { int PRIME = true ; int result = 1 ; Object $name = this .getName(); int result = result * 59 + ($name == null ? 43 : $name.hashCode()); long $score = Double.doubleToLongBits(this .score); result = result * 59 + (int )($score >>> 32 ^ $score); result = result * 59 + Arrays.deepHashCode(this .tags); return result; } public static class Square extends Shape { private final int width; private final int height; public Square (int width, int height) { this .width = width; this .height = height; } public boolean equals (Object o) { if (o == this ) { return true ; } else if (!(o instanceof EqualsAndHashCodeExample.Square)) { return false ; } else { EqualsAndHashCodeExample.Square other = (EqualsAndHashCodeExample.Square)o; if (!other.canEqual(this )) { return false ; } else if (!super .equals(o)) { return false ; } else if (this .width != other.width) { return false ; } else { return this .height == other.height; } } } protected boolean canEqual (Object other) { return other instanceof EqualsAndHashCodeExample.Square; } public int hashCode () { int PRIME = true ; int result = super .hashCode(); result = result * 59 + this .width; result = result * 59 + this .height; return result; } } }
构造函数@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor Java中class的一切起源于构造器。大家最喜欢的还是构造函数创建对象。这里有一点比较坑的是无参构造函数。当你自己添加一个带有参数的构造函数后,无参构造函数则别隐藏。通常也没啥问题,但当你使用jackson反序列化对象的时候就被恶心到了。jackson通过无参构造函数创建对象。因此,当你考虑这个class会用来序列化为json的时候,即必须手动添加一个无参数构造函数。
@NoArgsConstructor 当你想要创建一个valueobject,DDD中的值对象,要求实现Immutable,那么无参数构造器就不合适了。@NoArgsConstructor
会生成一个空的构造器。如果你设置了final field,那么编译会报错。如果你强制执行创建无参数构造器。即,@NoArgsConstructor(force = true)
,那么final的field会初始化为0
/false
/null
。通常适合与@Data
集成。
1 2 3 4 @NoArgsConstructor public static class NoArgsExample { @NonNull private String field; }
最终生成代码如下:
1 2 3 4 5 6 7 public static class NoArgsExample { @NonNull private String field; public NoArgsExample () { } }
对于final的字段,我认为我不会用空构造器来做这件事。所以,感觉这个参数force=true
不要也罢,鸡肋。
@RequiredArgsConstructor 一个class可以有很多属性,但你可能只关心其中的几个字段,那么可以使用@RequiredArgsConstructor
。@NonNull
将标注这个字段不应为null,初始化的时候会检查是否为空,否则抛出NullPointException
。在上面的无参构造函数中被忽略了。那么,对于关注的字段标注@NonNull
, @RequiredArgsConstructor
则会生成带有这些字段的构造器。
1 2 3 4 5 6 7 8 9 @RequiredArgsConstructor public class RequiredArgsExample { @NonNull private String field; private Date date; private Integer integer; private int i; private boolean b; private Boolean aBoolean; }
最终生成结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class RequiredArgsExample { @NonNull private String field; private Date date; private Integer integer; private int i; private boolean b; private Boolean aBoolean; public RequiredArgsExample (@NonNull String field) { if (field == null ) { throw new NullPointerException ("field" ); } else { this .field = field; } } }
只有@NonNull
会生成构造器。其他默认,Java的class初始化默认为null.false,0.
lombok提供了另一种初始化做法,静态初始化。即私有构造器,使用静态方法创建对象。这种做法看起来简单,但通常用的不多。因为静态初始化的东西很难mock,对测试不够友好。
1 2 3 4 5 6 7 8 9 @RequiredArgsConstructor(staticName = "of") public static class RequiredArgsStaticExample { @NonNull private String field; private Date date; private Integer integer; private int i; private boolean b; private Boolean aBoolean; }
最终生成代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class ConstructorExample <T> { private int x; private int y; @NonNull private T description; private ConstructorExample (@NonNull T description) { if (description == null ) { throw new NullPointerException ("description" ); } else { this .description = description; } } public static <T> ConstructorExample<T> of (@NonNull T description) { return new ConstructorExample (description); } }
@AllArgsConstructor 想要初始化所有字段。
1 2 3 4 5 6 @AllArgsConstructor(access = AccessLevel.PROTECTED) public class ConstructorExample <T> { private int x, y; @NonNull private T description; }
最终生成代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class ConstructorExample <T> { private int x; private int y; @NonNull private T description; protected ConstructorExample (int x, int y, @NonNull T description) { if (description == null ) { throw new NullPointerException ("description" ); } else { this .x = x; this .y = y; this .description = description; } } }
必用项@Data 1 @Data`是一个集合体。包含`Getter`,`Setter`,`RequiredArgsConstructor`,`ToString`,`EqualsAndHashCode
不可变对象valueobject @Value 这个看起来很美好,就是可以帮忙生成一个不可变对象。对于所有的字段都将生成final的。但我感觉有点失控。注解的优势应该是所见即所得,可以通过字面量来传递消息。而@Value
字段给字段加final会让人困惑,因为这更改了我们的定义。当我想声明一个Immutable对象的时候,我会显示的给字段加一个限定final。
同@Data
, @Value
是一个集合体。包含Getter
,AllArgsConstructor
,ToString
,EqualsAndHashCode
。
1 2 3 4 5 6 7 8 9 10 11 12 @Value public class Room { @NonNull private String id; private String name; private boolean active; private Date createTime; }
编译后
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 public final class Room { @NonNull private final String id; private final String name; private final boolean active; private final Date createTime; public Room (@NonNull String id, String name, boolean active, Date createTime) { if (id == null ) { throw new NullPointerException ("id" ); } else { this .id = id; this .name = name; this .active = active; this .createTime = createTime; } } @NonNull public String getId () { return this .id; } public String getName () { return this .name; } public boolean isActive () { return this .active; } public Date getCreateTime () { return this .createTime; } public boolean equals (Object o) { if (o == this ) { return true ; } else if (!(o instanceof Room)) { return false ; } else { Room other = (Room)o; Object this$id = this .getId(); Object other$id = other.getId(); if (this $id == null ) { if (other$id != null ) { return false ; } } else if (!this $id.equals(other$id)) { return false ; } label41: { Object this$name = this .getName(); Object other$name = other.getName(); if (this $name == null ) { if (other$name == null ) { break label41; } } else if (this $name.equals(other$name)) { break label41; } return false ; } if (this .isActive() != other.isActive()) { return false ; } else { Object this$createTime = this .getCreateTime(); Object other$createTime = other.getCreateTime(); if (this $createTime == null ) { if (other$createTime != null ) { return false ; } } else if (!this $createTime.equals(other$createTime)) { return false ; } return true ; } } } public int hashCode () { int PRIME = true ; int result = 1 ; Object $id = this .getId(); int result = result * 59 + ($id == null ? 43 : $id.hashCode()); Object $name = this .getName(); result = result * 59 + ($name == null ? 43 : $name.hashCode()); result = result * 59 + (this .isActive() ? 79 : 97 ); Object $createTime = this .getCreateTime(); result = result * 59 + ($createTime == null ? 43 : $createTime.hashCode()); return result; } public String toString () { return "Room(id=" + this .getId() + ", name=" + this .getName() + ", active=" + this .isActive() + ", createTime=" + this .getCreateTime() + ")" ; } }
最喜欢的项 @Builder 对于喜欢builder模式的人来说,声明式简化对象创建流程让一切看得美好。但是,手动复制字段,手动创建方法很让人不喜。@Builder
解决了刚需。
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 @Data @Builder(toBuilder = true) public class Room { @NonNull private String id; private String name; private boolean active; private Date createTime; @Singular private Set<String> occupations; public static void main (String[] args) { Room room = Room.builder().active(true ) .name("name" ) .id("id" ) .createTime(new Date ()) .occupation("1" ) .occupation("2" ) .build(); Assert.assertEquals(2 , room.getOccupations().size()); } }
这才是我们想要的建造者。对应生成的代码为:
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 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 package com.test.lombok;import java.util.ArrayList;import java.util.Collection;import java.util.Collections;import java.util.Date;import java.util.LinkedHashSet;import java.util.Set;import lombok.NonNull;import org.junit.Assert;public class Room { @NonNull private String id; private String name; private boolean active; private Date createTime; private Set<String> occupations; public static void main (String[] args) { Room room = builder().active(true ).name("name" ).id("id" ).createTime(new Date ()).occupation("1" ).occupation("2" ).build(); Assert.assertEquals(2L , (long )room.getOccupations().size()); } Room(@NonNull String id, String name, boolean active, Date createTime, Set<String> occupations) { if (id == null ) { throw new NullPointerException ("id" ); } else { this .id = id; this .name = name; this .active = active; this .createTime = createTime; this .occupations = occupations; } } public static Room.RoomBuilder builder () { return new Room .RoomBuilder(); } public Room.RoomBuilder toBuilder () { return (new Room .RoomBuilder()).id(this .id).name(this .name).active(this .active).createTime(this .createTime).occupations(this .occupations); } @NonNull public String getId () { return this .id; } public String getName () { return this .name; } public boolean isActive () { return this .active; } public Date getCreateTime () { return this .createTime; } public Set<String> getOccupations () { return this .occupations; } public void setId (@NonNull String id) { if (id == null ) { throw new NullPointerException ("id" ); } else { this .id = id; } } public void setName (String name) { this .name = name; } public void setActive (boolean active) { this .active = active; } public void setCreateTime (Date createTime) { this .createTime = createTime; } public void setOccupations (Set<String> occupations) { this .occupations = occupations; } public boolean equals (Object o) { if (o == this ) { return true ; } else if (!(o instanceof Room)) { return false ; } else { Room other = (Room)o; if (!other.canEqual(this )) { return false ; } else { label63: { Object this$id = this .getId(); Object other$id = other.getId(); if (this $id == null ) { if (other$id == null ) { break label63; } } else if (this $id.equals(other$id)) { break label63; } return false ; } Object this$name = this .getName(); Object other$name = other.getName(); if (this $name == null ) { if (other$name != null ) { return false ; } } else if (!this $name.equals(other$name)) { return false ; } if (this .isActive() != other.isActive()) { return false ; } else { Object this$createTime = this .getCreateTime(); Object other$createTime = other.getCreateTime(); if (this $createTime == null ) { if (other$createTime != null ) { return false ; } } else if (!this $createTime.equals(other$createTime)) { return false ; } Object this$occupations = this .getOccupations(); Object other$occupations = other.getOccupations(); if (this $occupations == null ) { if (other$occupations != null ) { return false ; } } else if (!this $occupations.equals(other$occupations)) { return false ; } return true ; } } } } protected boolean canEqual (Object other) { return other instanceof Room; } public int hashCode () { int PRIME = true ; int result = 1 ; Object $id = this .getId(); int result = result * 59 + ($id == null ? 43 : $id.hashCode()); Object $name = this .getName(); result = result * 59 + ($name == null ? 43 : $name.hashCode()); result = result * 59 + (this .isActive() ? 79 : 97 ); Object $createTime = this .getCreateTime(); result = result * 59 + ($createTime == null ? 43 : $createTime.hashCode()); Object $occupations = this .getOccupations(); result = result * 59 + ($occupations == null ? 43 : $occupations.hashCode()); return result; } public String toString () { return "Room(id=" + this .getId() + ", name=" + this .getName() + ", active=" + this .isActive() + ", createTime=" + this .getCreateTime() + ", occupations=" + this .getOccupations() + ")" ; } public static class RoomBuilder { private String id; private String name; private boolean active; private Date createTime; private ArrayList<String> occupations; RoomBuilder() { } public Room.RoomBuilder id (String id) { this .id = id; return this ; } public Room.RoomBuilder name (String name) { this .name = name; return this ; } public Room.RoomBuilder active (boolean active) { this .active = active; return this ; } public Room.RoomBuilder createTime (Date createTime) { this .createTime = createTime; return this ; } public Room.RoomBuilder occupation (String occupation) { if (this .occupations == null ) { this .occupations = new ArrayList (); } this .occupations.add(occupation); return this ; } public Room.RoomBuilder occupations (Collection<? extends String> occupations) { if (this .occupations == null ) { this .occupations = new ArrayList (); } this .occupations.addAll(occupations); return this ; } public Room.RoomBuilder clearOccupations () { if (this .occupations != null ) { this .occupations.clear(); } return this ; } public Room build () { Set occupations; switch (this .occupations == null ? 0 : this .occupations.size()) { case 0 : occupations = Collections.emptySet(); break ; case 1 : occupations = Collections.singleton(this .occupations.get(0 )); break ; default : Set<String> occupations = new LinkedHashSet (this .occupations.size() < 1073741824 ? 1 + this .occupations.size() + (this .occupations.size() - 3 ) / 3 : 2147483647 ); occupations.addAll(this .occupations); occupations = Collections.unmodifiableSet(occupations); } return new Room (this .id, this .name, this .active, this .createTime, occupations); } public String toString () { return "Room.RoomBuilder(id=" + this .id + ", name=" + this .name + ", active=" + this .active + ", createTime=" + this .createTime + ", occupations=" + this .occupations + ")" ; } } }
总结 lombok还提供了其他几个注解,以及还有好多内置的参数没有讲解。但是,根据2-8原理,我们根本不需要。上面这几个足够了。更多的注解只会增加理解阅读难度。
参考 https://projectlombok.org/features/all http://kriszhang.com/lombok/