lombok的使用
文章较长,可以按需查阅
导入依赖
首先Maven项目在pom.xml导入依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
一、@getter、@Setter、@toString
1、@getter、@Setter分别生成getxxx()和setxxx()方法
可以将注解加需要生成getter和setter方法的成员变量上。
如果加在了类上,但是要某个成员变量生成特殊getter和setter怎么办?
可以直接手动编写该变量的getter和sette方法,当lombok检测到你已经为该变量编写了相应的getter和setter方法后,就不会再自动生成了。
2、@toString生成toString()方法,按顺序打印类名称以及每个字段,并以逗号分隔
二、@NoArgsConstructor、@RequiredArgsConstructor、@AllArgsConstructor
1、@NoArgsConstructor无参构造函数
@NoArgsConstructor
注解共有staticName、onConstructor、access以及force四个属性参数可以进行配置:
staticName
staticName代表的是是否生成静态构造方法,也就是说当staticName属性有值时则会生成一个静态构造方法,这时无参构造方法会被私有,然后创建一个指定名称的静态构造方法,并且是公有的,如下所示:
/**
* 编译前代码
*/
@RequiredArgsConstructor(staticName = "UserStatic")
public class UserInfo() {
private String username;
private String password;
}
/**
* 编译后代码
*/
public class UserInfo() {
private String username;
private String password;
private UserInfo() {
}
public UserStatic() {
return new UserStatic();
}
}
onConstructor
onConstructor
经常写Spring或者SpringBoot代码的人应该知道,Spring对于依赖注入提供了三种写法,分别是属性注入、Setter方法注入以及构造器注入,但是在日常工作中我们更多采用的是依赖于@Autowired注解方式进行依赖注入,不过过多的依赖注入会使我们的代码过于冗长,甚至Spring4.0起就已经开始不推荐这种写法了,而是推荐使用Setter方法注入以及构造器注入,lombok的生成构造器的方法就可以很方便的实现这种写法。
举一个通过构造器注入的例子:
@Controller
public class SysLoginController() {
private final TokenUtils tokenUtils;
private final SysLoginService sysLoginService;
/**
* 在这里 @Autowired 是可以省略的,在这里使用只是为了介绍 onConstructor 参数
*/
@Autowired
public SysLoginController (TokenUtils tokenUtils, SysLoginService sysLoginService) {
this.tokenUtils = tokenUtils;
this.sysLoginService = sysLoginService;
}
}
这样注入Bean在数量较多时我们仍需编写大量代码,这个时候就可以使用@RequiredArgsConstructor注解来解决这个问题,至于为什么不使用@AllArgsConstructor注解是因为这个注解是针对所有参数的,而在这个情境下,我们只需构造Bean所对应的属性而不是非Bean,所以我们只需在Bean对应的属性前加上final关键字进行修饰就可以只生成需要的有参构造函数,如下所示:
/**
* 编译前
*/
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class SysLoginController() {
private final TokenUtils tokenUtils;
private final SysLoginService sysLoginService;
}
/**
* 编译后
*/
public class SysLoginController() {
private final TokenUtils tokenUtils;
private final SysLoginService sysLoginService;
@Autowired
public SysLoginController (TokenUtils tokenUtils, SysLoginService sysLoginService) {
this.tokenUtils = tokenUtils;
this.sysLoginService = sysLoginService;
}
}
access
有的时候我们会使用单例模式,这个时候需要我们创造一个私有的无参构造方法,那么就可以使用access这样一个属性来设置构造起的权限,如下所示:
/**
* 编译前代码
*/
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class UserInfo() {
private String username;
private String password;
}
/**
* 编译后代码
*/
public class UserInfo() {
private String username;
private String password;
private UserInfo() {
}
}
access的可选等级:
public enum AccessLevel {
PUBLIC,
MODULE,
PROTECTED,
PACKAGE,
PRIVATE,
NONE;
private AccessLevel() {
}
}
force
当类中有被final关键字修饰的字段未被初始化时,编译器会报错,这时也可以设置force属性为true来为字段根据类型生成一个默认值0/false/null,这样编译器就不会再报错了,如下所示:
/**
* 编译前代码
*/
@RequiredArgsConstructor(force = true)
public class UserInfo() {
private final String gender;
private String username;
private String password;
}
/**
* 编译后代码
*/
public class UserInfo() {
private final String gender = null;
private String username;
private String password;
private UserInfo() {
}
}
2、@RequiredArgsConstructor
@RequiredArgsConstructor
在类上使用,这个注解可以生成带参或者不带参的构造方法。
若带参数,只能是类中所有带有@NonNull注解的和以final修饰的未经初始化的字段,如下所示:
/**
* 编译前代码
*/
@RequiredArgsConstructor
public class UserInfo() {
private final String gender;
@NonNull
private String username;
private String password;
}
/**
* 编译后代码
*/
public class UserInfo() {
private final String gender;
@NonNull
private String username;
private String password;
public UserInfo(String gender, @NonNull String username) {
if (username == null) {
throws new NullPointerException("username is marked @NonNull but is null");
} else {
this.gender = gender;
this.username = username;
}
}
}
参数配置参照@NoArgsConstructor
源码详解
3、@AllArgsConstructor
@AllArgsConstructor在类上使用,这个注解可以生成全参构造函数,且默认不生成无参构造函数。
不过需要注意的是,这里所说的全参并不包括已经被初始化的被final关键字修饰的字段,因为字段一旦被final关键字修饰被赋值后就不能再被修改,如下所示:
/**
* 编译前代码
*/
@RequiredArgsConstructor
public class UserInfo() {
private final String gender;
private final Integer age = 18;
private String username;
private String password;
}
/**
* 编译后代码
*/
public class UserInfo() {
private final String gender;
private final Integer age = 18;
private String username;
private String password;
public User(String gender, String username, String password) {
this.gender = gender;
this.username = username;
this.password = password;
}
}
参数配置参照@NoArgsConstructor
源码详解
三、@Data
@Data注解包含了@Getter@Setter,且有toString(),equals(),canEqual()等方法
四、@Builder、@Singular
@Builder
在lombok日常使用场景中,总会碰到对象中包含集合的情况,这种情况下,我们对于对象中集合的赋值就需要像其他属性一样使用set方法进行赋值操作:
@Data
@Builder
class Student{
private String name;
private List<String> skills;
}
builder源码剖析:
public static class StudentBuilder {
// 省略其他部分
public Student.StudentBuilder skills(List<String> skills) {
this.skills = skills;
return this;
}
}
这种方式来初始化集合属性不能说是错的,但是用起来还是不够人性化,我们对集合进行构建时主要也是为其添加元素,因此能不能有一个专门为该集合添加元素的方法,同时将集合的实例化隐藏在代码内部的操作呢,答案是肯定的,这就是接下来介绍的@Singular的作用.
@Singular
/**
* 编译前代码
*/
@Builder
class Student{
private String name;
@Singular
private List<String> skills;
}
/**
* 编译后代码
*/
class Student {
private String name;
private List<String> skills;
Student(String name, List<String> skills) {
this.name = name;
this.skills = skills;
}
public static StudentBuilder builder() {
return new StudentBuilder();
}
public static class StudentBuilder {
private String name;
private ArrayList<String> skills;
StudentBuilder() {
}
public StudentBuilder name(String name) {
this.name = name;
return this;
}
public StudentBuilder skill(String skill) {
if (this.skills == null) {
this.skills = new ArrayList();
}
this.skills.add(skill);
return this;
}
public StudentBuilder skills(Collection<? extends String> skills) {
if (skills == null) {
throw new NullPointerException("skills cannot be null");
} else {
if (this.skills == null) {
this.skills = new ArrayList();
}
this.skills.addAll(skills);
return this;
}
}
public StudentBuilder clearSkills() {
if (this.skills != null) {
this.skills.clear();
}
return this;
}
public Student build() {
List skills;
switch (this.skills == null ? 0 : this.skills.size()) {
case 0:
skills = Collections.emptyList();
break;
case 1:
skills = Collections.singletonList(this.skills.get(0));
break;
default:
skills = Collections.unmodifiableList(new ArrayList(this.skills));
}
return new Student(this.name, skills);
}
public String toString() {
return "Student.StudentBuilder(name=" + this.name + ", skills=" + this.skills + ")";
}
}
}
对比与上一份代码,加入了@Singular注解后,lombok为我们添加了一个为集合添加元素的方法skill(),当我们不指定方法名时,lombok会根据英文自动推导出方法名,如:skills -> skill,集合名称为:skills,那么它会将复数去掉后,剩下的单词就是方法名称了。我们可以自定义方法名的名称@Singular(“addSkill”)。如果使用了不规范的命名则一定要指定方法名。
如有错误,还请多多指教!
转载或者引用本文内容请注明来源及原作者:橘足轻重;