lombok
Lombok是一个可以通过简单的注解形式来帮助我们简化消除一些必须有但显得很臃肿的Java代码的工具,通过使用对应的注解,可以在编译源码的时候生成对应的方法。官方地址:https://projectlombok.org/,github地址:https://github.com/rzwitserloot/lombok。
lombok
技术本身没有好坏之分,只有把这个技术用在合适的地方,才能发挥它的价值。
那些一味吐槽lombok
没用的人,和那些觉得自己掌握了lombok
就高人一等的人,我们“文明观赏”就行。
常用注解
@Getter和 @Setter
作用在字段或者类上,自动为字段生成getter/setter方法,默认是public.
使用lombok的代码
public class Employee {
@Getter
@Setter
private boolean employed;
@Setter(AccessLevel.PROTECTED)
private String name;
}
等价的纯java代码
public class Employee {
private boolean employed;
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
标注在属性上,当使用方法注入null值时,会抛出NullPointerException
异常
使用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
生成toString()
方法,默认所有非静态变量都会被使用
参数说明
includeFieldNames
: 是否包含字段名,true
包含exclude
:排除字段of
:包含字段callSuper
:输出父类的 toString()结果
示例:
对于如下类
public class Employee {
@Getter
@Setter
private boolean employed;
@Setter(AccessLevel.PUBLIC)
@NonNull
private String name;
private String password;
}
不同注解对应的结果
注解 | 输出 |
---|---|
@ToString() | Employee(employed=false, name=null, password=null) |
@ToString(includeFieldNames = false) | Employee(false, null, null) |
@ToString(exclude = {“password”}) | Employee(employed=false, name=null) |
@EqualsAndHashCode
生成equals()
和hashCode()
方法,和ToString()
注解类似。
示例:
使用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;
}
}
@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor
生成构造器
@Data
相当于同时使用了@ToString, @EqualsAndHashCode、@Getter、@Setter这些注解。
使用@Data
会触发Lombok使用所有使用了@NonNull
或者final
属性生成构造函数。
参数:staticConstructor
静态工厂方法名,该方法生成对象实例
Lombok代码
@Data(staticConstructor="instance")
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 instance(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 + ")";
}
}
@Log
作用在类上,用于生成Log对象
@Synchronized
同步方法,会默认生成一个private的$LOCK
对象,在方法调用是给$LOCK
加锁。
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);
}
}
@Builder
给当前类生成一个Builder对象。
@ Delegate
为该类生成一些列的方法,这些方法都来自于List接口.
标注在List类型的字段上
@Delegate
private List<User> list=new ArrayList<>();
@Cleanup
自动释放资源
@Cleanup InputStreamReader reader=new InputStreamReader(new ByteArrayInputStream(bs));
默认调用流的 close
方法,可以通过参数 value
设置
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();
}
}
总结!!
lombok
褒贬不一,使用lombok
提供的注解可以大大简化代码,提高开发效率。但是使用了过多的注解,导致项目可读性较差,项目维护起来存在一定的问题。
在使用时,应该根据项目的实际需求来决定是否使用lombok
,团队人员较少,各个人员技术差异不大,或者小型项目,可以考虑使用lombok
.当项目开发人员技术层次不齐时,应该慎重考虑是否使用,毕竟使用快捷键生成 Getter
和Setter
也非常方便,废不了多少事。
此外,lombok
官方还提供了将 lombok
注解替换成对应java代码的工具delombok
,可以参考官网说明。
lombok
技术本身没有好坏之分,只有把这个技术用在合适的地方,才能发挥它的价值。
那些一味吐槽lombok
没用的人,和那些觉得自己掌握了lombok
就高人一等的人,我们“文明观赏”就行。