引入lombok
- 在maven中添加依赖
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
使用
导入的包:
import lombok.*;
直接在相应的实体类上加上@Data注解即可;
比如一个简单的Person类,用常规的写法:
public class Person {
private String name;
private String address;
private Integer age;
private String hobbit;
private String phone;
public Person() {
}
public Person(String name, String address, Integer age, String hobbit, String phone) {
this.name = name;
this.address = address;
this.age = age;
this.hobbit = hobbit;
this.phone = phone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getHobbit() {
return hobbit;
}
public void setHobbit(String hobbit) {
this.hobbit = hobbit;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
", age=" + age +
", hobbit='" + hobbit + '\'' +
", phone='" + phone + '\'' +
'}';
}
}
用@Data的写法:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private String name;
private String address;
private Integer age;
private String hobbit;
private String phone;
}
自动生成相关的方法:
常用的几个注解:
- @Data : 注在类上,提供类的get、set、equals、hashCode、canEqual、toString方法
注意的是,同时使用@Data 和 @AllArgsConstructor 后 ,默认的无参构造函数失效,如果需要它,要重新设置 @NoArgsConstructor
- @AllArgsConstructor : 注在类上,提供类的全参构造
相当于:
public Person(String name, String address, Integer age, String hobbit, String phone) {
this.name = name;
this.address = address;
this.age = age;
this.hobbit = hobbit;
this.phone = phone;
}
如果变量使用了NotNull annotation , 会进行是否为空的校验, 全部参数的构造函数的自动生成,该注解的作用域也是只有在实体类上,参数的顺序与属性定义的顺序一致。
- @NoArgsConstructor : 注在类上,提供类的无参构造
相当于:
public Person() {
}
- @Setter : 注在
属性/方法
上,提供 set 方法。(放在属性上表示只给这个属性提供set方法;放在方法上,表示为所有属性提供set方法) - @Getter : 注在
属性/方法
上,提供 get 方法(作用同@Setter注解) - @EqualsAndHashCode : 注在类上,提供对应的 equals 和 hashCode 方法
- @Log4j/@Slf4j : 注在类上,提供对应的 Logger 对象,变量名为 log
- @NonNull:用于标记类中不能允许为 null 的字段或者参数上,若@NonNull 标记的变量为 null,抛出 NullPointException (NPE) 异常。
使用方法如下:
- @ToString:生成toString 方法
@Builder:使用 @Builder 注解为给我们的实体类自动生成 builder() 方法,并且直接根据字段名称方法进行字段赋值,最后使用 build()方法构建出一个实体对象。
@Builder
@Data
public class Person {
private String address;
public static void main(String[] args) {
Person person = Person.builder().address("辽宁").build();
System.out.println("build的结果是:"+person.getAddress());
}
}
打印结果:
但是 @Builder 不支持父类字段的生成,当一个实体类存在父类时,@Builder 只能生成当前类的字段构建方法。若需要用到父类的字段方法时, Lombok 提供了新的注解@SuperBuilder
来应对这种情况,下面是 @SuperBuilder 注解的使用方式。
@SuperBuilder
@Data
public class People {
private String name;
}
@SuperBuilder
@Data
public class Person extends People {
private String address;
public static void main(String[] args) {
Person person = Person.builder().name("父类字段build").build();
System.out.println("build的结果是:" + person.getName());
}
}
打印结果:
- @SneakyThrows:主要用于在没有 throws 关键字的情况下,隐蔽地抛出受检查异常,为我们平常开发中需要异常抛出时省去的 throw 操作。
比如,日期与字符串之间的相互转化
,java代码如下:
需要在方法上throws
抛出ParseException
异常信息。
如果在方法上使用@SneakyThrows
注解,则代码如下:
可以看出,方法上无需添加throws ParseException
。
- @Singular
@Singular注解使用需要注意两点:
①作用于集合上
②与@Builder注解配合使用
@Builder
@ToString
private static class Student04{
private String name;
private Integer age;
@Singular("addHobby")//addHobby是在Singular注解里面设置的一个方法名字
private List<String> hobby;
public static void main(String[] args) {
//实体中我们通过@Singular注解添加了一个方法addHobby,同时build了read和run,那么read和run就自动添加进了List<String>中
Student04 student04 = Student04.builder().name("刘亦菲").age(10).addHobby("read").addHobby("run").build();
System.out.println(student04);
}
}
打印结果:
- @Cleanup
@Cleanup 用于标记需要释放清理操作的资源对象变量,如 FileInputStream, FileOutputStream 等,标记之后资源对象使用完毕后,就会被自动关闭和清理。
public static void main(String[] args) throws FileNotFoundException {
@Cleanup InputStream in = new FileInputStream(args[0]);
@Cleanup OutputStream out = new FileOutputStream(args[1]);
byte[] b = new byte[10000];
while (true) {
int r = 0;
try {
r = in.read(b);
} catch (IOException e) {
e.printStackTrace();
}
if (r == -1) {
break;
}
try {
out.write(b, 0, r);
} catch (IOException e) {
e.printStackTrace();
}
}
}
- @RequiredArgsConstructor
会生成一个包含常量(final),和标识了@NotNull的变量 的构造方法。
在我们写controller或者Service层的时候,需要注入很多的mapper接口或者另外的service接口,这时候就会写很多的@Autowired注解,代码看起来很乱,还很繁琐。有了@RequiredArgsConstructor注解,我们就可以减少@Autowired的书写。
使用方法:在构造方法上添加注解。
@RequiredArgsConstructor(onConstructor=@_({@AnnotationsGoHere}))
OR
@RequiredArgsConstructor
友情提示:类上加上@RequiredArgsConstructor,需要注入的类要用final声明,或者使用@NonNull。
@RestController
@RequestMapping("/test")
@Slf4j
// 作用在类上
@RequiredArgsConstructor(onConstructor = @_({@Autowired}))
public class TestController {
// 必须声明为final类型
private final TestService testService;
// 或者使用Lombok的注解
@NonNull
private TestMapper testMapper;
@GetMapping("/hello3")
public int hello3(){
Test test = new Test();
test.setName("sss");
test.setId("0");
return testMapper.insert(test);
}
}
综合案例:
package com.example.domain;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
@Slf4j
public class LombokDemo {
@Getter
@Setter
@ToString(of = {"name", "sex"})//ToString 可以配字段
@EqualsAndHashCode(of = {"name", "sex"})//指定哪些字段参与 equals hashcode
private static class Student01 {
private String name;
private Integer age;
private Byte sex;
}
@NoArgsConstructor(access = AccessLevel.PRIVATE) // 无参构造方法,默认public(可以通过access设置方法权限,比如设置为private,变成单例模式)
@AllArgsConstructor //全参构造函数
private static class Student02 {
private String name;
private Integer age;
private Byte sex;
}
@Data
@Value
private static class Student03 {
private String name;
private Integer age;
private Byte sex;
}
@Builder
@ToString
private static class Student04 {
private String name;
private Integer age;
@Singular("addHobby")//addHobby是在Singular注解里面设置的一个方法名字
private List<String> hobby;
public static void main(String[] args) {
//实体中我们通过@Singular注解添加了一个方法addHobby,同时build了read和run,那么read和run就自动添加进了List<String>中
Student04 student04 = Student04.builder().name("刘亦菲").age(10).addHobby("read").addHobby("run").build();
System.out.println(student04);
}
}
@SneakyThrows
public void shitHappens() {
Thread.sleep(1000);
}
//@Cleanup 自动关闭资源(省去了最终finally必须关闭资源的步骤)
public void copyFile(String input, String output) throws IOException {
@Cleanup FileInputStream inputStream = new FileInputStream(input);
@Cleanup FileOutputStream outputStream = new FileOutputStream(output);
byte[] b = new byte[65536];
while (true) {
int r = inputStream.read(b);
if (r == -1) {
break;
}
outputStream.write(b, 0, r);
}
}
@Data
@Accessors(fluent = true)
private static class Student05 {
private String name;
private Integer age;
public static void main(String[] args) {
Student05 student05 = new Student05();
student05.age(10);//fluent = true只是省去了传统java的get、set形式,不建议使用
System.out.println(student05.age);
}
}
@Data
@Accessors(chain = true)
private static class Student06 {
private String name;
private Integer age;
public static void main(String[] args) {
Student06 student06 = new Student06();//
student06.setAge(10).setName("刘亦菲");//chain = true能够使实体连续set,成为一个链条
}
}
}