第十三节:使用Lombok简化你的代码

在开发过程中,通常都会定义大量的JavaBean,然后通过IDE去产生其属性的构造器、getter、setter、equals、hashcode、toString方法,当要增加属性或者对某个属性进行改变时,比如命名、类型等,都需要重新去产生上面提到的这些方法。这样重复的劳动没有任何意义,Lombok里面的注解可以轻松解决这些问题。

lombok实现的原理:主要是通过抽象语法树(AST),在编译处理后,对应到有其注解的类,那么注解编译器就会自动去对应项目中的注解对应到在lombok语法树中的注解文件,并经过自动编译对应来产生对应类中的getter或者setter方法,达到简化代码的目的

pom.xml添加lombok

  1. <dependency>
  2. <groupId>org.projectlombok</groupId>
  3. <artifactId>lombok</artifactId>
  4. <optional>true</optional>
  5. </dependency>

@Getter @Setter注解

这一对注解从名字上就很好理解,用在成员变量前面,相当于为成员变量生成对应的get和set方法,同时还可以为生成的方法指定访问修饰符,当然,默认为public,直接来看下面的简单的例子:

  1. // Rumenz.java
  2. /**
  3. * @className: Rumenz
  4. * @description: TODO 类描述
  5. * @author: 入门小站 rumenz.com
  6. * @date: 2021/12/9
  7. **/
  8. public class RumenzGetSet {
  9. @Getter @Setter
  10. private Integer id;
  11. @Getter @Setter
  12. private String name;
  13. }
  • 等价于
    ```
    public class RumenzGetSet {
    private Integer id;
    private String name;

    public Integer getId() {

    1. return id;

    }

    public void setId(Integer id) {

    1. this.id = id;

    }

    public String getName() {

    1. return name;

    }

    public void setName(String name) {

    1. this.name = name;

    }
    }

@RestController
@RequestMapping(“/rumenz”)
public class RumenzController {

  1. @GetMapping("/index")
  2. public String index(){
  3. RumenzGetSet r=new RumenzGetSet();
  4. r.setId(1);
  5. r.setName("入门小站");
  6. return r.getId()+r.getName();
  7. }

}

  1. > 访问`http://127.0.0.1:8080/rumenz/index`返回`1入门小站`
  2. ### @NonNull注解
  3. > 这个注解可以用在成员方法或者构造方法的参数前面,会自动产生一个关于此参数的非空检查,如果参数为空,则抛出一个空指针异常,举个例子来看看

public class RumenzNonNull {
@Getter @Setter @NonNull
private Integer id;
@Getter @Setter @NonNull
private String name;
}

  1. - 等价于

public class RumenzNonNull {
private Integer id;
private String name;

  1. public Integer getId() {
  2. return id;
  3. }
  4. public void setId(Integer id) {
  5. if (id == null) throw new java.lang.NullPointerException("id");
  6. this.id = id;
  7. }
  8. public String getName() {
  9. return name;
  10. }
  11. public void setName(String name) {
  12. if (name == null) throw new java.lang.NullPointerException("name");
  13. this.name = name;
  14. }

}

@GetMapping(“/index1”)
public String index1(){
RumenzNonNull r=new RumenzNonNull();
r.setId(1);
r.setName(null);

  1. return r.getId()+r.getName();

}

  1. > 访问`http://127.0.0.1:8080/rumenz/index1`报错`java.lang.NullPointerException: name is marked non-null but is null`
  2. ### @ToString

@ToString
public class RumenzToString {

  1. @Getter @Setter
  2. private Integer id;
  3. @Getter @Setter
  4. private String name;
  5. @Override
  6. public String toString() {
  7. return "RumenzToString{" +
  8. "id=" + id +
  9. ", name='" + name + '\'' +
  10. '}';
  11. }

}

  1. - 等价于

public class RumenzToString {

  1. private Integer id;
  2. private String name;
  3. public Integer getId() {
  4. return id;
  5. }
  6. public void setId(Integer id) {
  7. this.id = id;
  8. }
  9. public String getName() {
  10. return name;
  11. }
  12. public void setName(String name) {
  13. this.name = name;
  14. }
  15. @Override
  16. public String toString() {
  17. return "RumenzToString{" +
  18. "id=" + id +
  19. ", name='" + name + '\'' +
  20. '}';
  21. }

}

@GetMapping(“/index2”)
public String index2(){
RumenzToString r=new RumenzToString();
r.setId(1);
r.setName(“入门小站”);
return r.toString();
}

  1. > 访问`http://127.0.0.1:8080/rumenz/index1`返回`RumenzToString{id=1, name='入门小站'}`
  2. ### EqualsAndHashCode注解

@EqualsAndHashCode
public class RumenzEqualsAndHashCode {

  1. @Getter @Setter
  2. private Integer id;
  3. @Getter @Setter
  4. private String name;

}

  1. - 等价于

public class RumenzEqualsAndHashCode {
private Integer id;
private String name;

  1. public Integer getId() {
  2. return id;
  3. }
  4. public void setId(Integer id) {
  5. this.id = id;
  6. }
  7. public String getName() {
  8. return name;
  9. }
  10. public void setName(String name) {
  11. this.name = name;
  12. }
  13. @Override
  14. public boolean equals(Object o) {
  15. if (this == o) return true;
  16. if (!(o instanceof RumenzEqualsAndHashCode)) return false;
  17. RumenzEqualsAndHashCode that = (RumenzEqualsAndHashCode) o;
  18. return id.equals(that.id) &&
  19. name.equals(that.name);
  20. }

}

@GetMapping(“/index3”)
public String index3(){
RumenzEqualsAndHashCode r1=new RumenzEqualsAndHashCode();
r1.setId(1);
r1.setName(“入门小站”);

  1. RumenzEqualsAndHashCode r2=new RumenzEqualsAndHashCode();
  2. r2.setId(1);
  3. r2.setName("入门小站");
  4. if(r1.equals(r2)){
  5. return "相等";
  6. }
  7. return "不相等";

}

  1. ### @Data注解
  2. - 1)生成无参构造方法;
  3. - 2)属性的set/get方法;
  4. - 3equals(), hashCode(), toString(), canEqual()方法。

@Data(staticConstructor=”of”)
public class RumenzData {

  1. private Integer id;
  2. private String name;

}
//等价于

public class RumenzData {
private Integer id;
private String name;

  1. private RumenzData() {
  2. }
  3. public static RumenzData of() {
  4. return new RumenzData();
  5. }
  6. public Integer getId() {
  7. return this.id;
  8. }
  9. public String getName() {
  10. return this.name;
  11. }
  12. public void setId(final Integer id) {
  13. this.id = id;
  14. }
  15. public void setName(final String name) {
  16. this.name = name;
  17. }
  18. public boolean equals(final Object o) {
  19. if (o == this) {
  20. return true;
  21. } else if (!(o instanceof RumenzData)) {
  22. return false;
  23. } else {
  24. RumenzData other = (RumenzData)o;
  25. if (!other.canEqual(this)) {
  26. return false;
  27. } else {
  28. Object this$id = this.getId();
  29. Object other$id = other.getId();
  30. if (this$id == null) {
  31. if (other$id != null) {
  32. return false;
  33. }
  34. } else if (!this$id.equals(other$id)) {
  35. return false;
  36. }
  37. Object this$name = this.getName();
  38. Object other$name = other.getName();
  39. if (this$name == null) {
  40. if (other$name != null) {
  41. return false;
  42. }
  43. } else if (!this$name.equals(other$name)) {
  44. return false;
  45. }
  46. return true;
  47. }
  48. }
  49. }
  50. protected boolean canEqual(final Object other) {
  51. return other instanceof RumenzData;
  52. }
  53. public int hashCode() {
  54. int PRIME = true;
  55. int result = 1;
  56. Object $id = this.getId();
  57. int result = result * 59 + ($id == null ? 43 : $id.hashCode());
  58. Object $name = this.getName();
  59. result = result * 59 + ($name == null ? 43 : $name.hashCode());
  60. return result;
  61. }
  62. public String toString() {
  63. return "RumenzData(id=" + this.getId() + ", name=" + this.getName() + ")";
  64. }

}

@GetMapping(“/index4”)
public String index4(){
RumenzData of = RumenzData.of();
of.setName(“入门小站”);
String name = of.getName();
return name;
}

  1. ### @Cleanup注解
  2. > 这个注解用在变量前面,可以保证此变量代表的资源会被自动关闭,默认是调用资源的close()方法,如果该资源有其它关闭方法,可使用@Cleanup(“methodName”)来指定要调用的方法,就用输入输出流来举个例子吧:
  3. `

@GetMapping(“/index5”)
public String index5() throws IOException {

File file = ResourceUtils.getFile(“classpath:application.properties”);
@Cleanup InputStream inputStream = new FileInputStream(file);

byte b[]=new byte[(int) file.length()];
inputStream.read(b);
//@Cleanup 代替了 inputStream.close();
return new String(b);
}

  1. > 等价于

@GetMapping({“/index5”})
public String index5() throws IOException {
File file = ResourceUtils.getFile(“classpath:application.properties”);
FileInputStream inputStream = new FileInputStream(file);

  1. String var4;
  2. try {
  3. byte[] b = new byte[(int)file.length()];
  4. inputStream.read(b);
  5. var4 = new String(b);
  6. } finally {
  7. if (Collections.singletonList(inputStream).get(0) != null) {
  8. inputStream.close();
  9. }
  10. }
  11. return var4;

}

  1. ### @NoArgsConstructor注解
  2. > @NoArgsConstructor在类上使用,它可以提供一个无参构造器

@NoArgsConstructor
public class RumenzNoArgsConstructor {
private Integer id;
private String name;
}

  1. > 等价于

public class RumenzNoArgsConstructor {
private Integer id;
private String name;

  1. public RumenzNoArgsConstructor() {
  2. }

}

  1. ### @RequiredArgsConstructor注解
  2. > 指定final的属性生成构造方法

@ToString
@RequiredArgsConstructor
public class RumenzRequiredArgsConstructor {
private Integer id;
private final String name;
}

  1. // 等价于

public class RumenzRequiredArgsConstructor {
private Integer id;
private final String name; //final

  1. public String toString() {
  2. return "RumenzRequiredArgsConstructor(id=" + this.id + ", name=" + this.name + ")";
  3. }
  4. public RumenzRequiredArgsConstructor(final String name) {
  5. this.name = name;
  6. }

}

  1. ### @AllArgsConstructor注解
  2. > 类中所有的字段都生成一个有参的构造方法.

@ToString
@AllArgsConstructor
public class RumenzAllArgsConstructor {
private Integer id;
private String name;
}

  1. //等价于

public class RumenzAllArgsConstructor {
private Integer id;
private String name;

  1. public String toString() {
  2. return "RumenzAllArgsConstructor(id=" + this.id + ", name=" + this.name + ")";
  3. }
  4. public RumenzAllArgsConstructor(final Integer id, final String name) {
  5. this.id = id;
  6. this.name = name;
  7. }

}

  1. ### @Value注解
  2. - 1)有参构造方法;
  3. - 2)只添加@Value注解,没有其他限制,那么类属性会被编译成final的,因此只有get方法,而没有set方法。

@ToString
@Value
public class RumenzValue {
private Integer id;
private String name;
}

  1. // 等价于

public final class RumenzValue {
private final Integer id;
private final String name;

  1. public RumenzValue(final Integer id, final String name) {
  2. this.id = id;
  3. this.name = name;
  4. }
  5. public Integer getId() {
  6. return this.id;
  7. }
  8. public String getName() {
  9. return this.name;
  10. }
  11. public boolean equals(final Object o) {
  12. if (o == this) {
  13. return true;
  14. } else if (!(o instanceof RumenzValue)) {
  15. return false;
  16. } else {
  17. RumenzValue other = (RumenzValue)o;
  18. Object this$id = this.getId();
  19. Object other$id = other.getId();
  20. if (this$id == null) {
  21. if (other$id != null) {
  22. return false;
  23. }
  24. } else if (!this$id.equals(other$id)) {
  25. return false;
  26. }
  27. Object this$name = this.getName();
  28. Object other$name = other.getName();
  29. if (this$name == null) {
  30. if (other$name != null) {
  31. return false;
  32. }
  33. } else if (!this$name.equals(other$name)) {
  34. return false;
  35. }
  36. return true;
  37. }
  38. }
  39. public int hashCode() {
  40. int PRIME = true;
  41. int result = 1;
  42. Object $id = this.getId();
  43. int result = result * 59 + ($id == null ? 43 : $id.hashCode());
  44. Object $name = this.getName();
  45. result = result * 59 + ($name == null ? 43 : $name.hashCode());
  46. return result;
  47. }
  48. public String toString() {
  49. return "RumenzValue(id=" + this.getId() + ", name=" + this.getName() + ")";
  50. }

}

  1. ### @SneakyThrows注解
  2. > 这个注解用在方法上,可以将方法中的代码用try-catch语句包裹起来,捕获异常并在catch中用Lombok.sneakyThrow(e)把异常抛出,可以使用@SneakyThrows(Exception.class)的形式指定抛出哪种异常,很简单的注解,直接看个例子:

@SneakyThrows
@GetMapping(“/index9”)
public String index9() {

  1. //使用@SneakyThrows就不用显式抛出异常了
  2. File file = ResourceUtils.getFile("classpath:application.properties");
  3. @Cleanup InputStream inputStream = new FileInputStream(file);
  4. byte b[]=new byte[(int) file.length()];
  5. inputStream.read(b);
  6. //@Cleanup 代替了 inputStream.close();
  7. return new String(b);

}

  1. // 等价于

@GetMapping({“/index9”})
public String index9() {
try {
File file = ResourceUtils.getFile(“classpath:application.properties”);
FileInputStream inputStream = new FileInputStream(file);

  1. String var4;
  2. try {
  3. byte[] b = new byte[(int)file.length()];
  4. inputStream.read(b);
  5. var4 = new String(b);
  6. } finally {
  7. if (Collections.singletonList(inputStream).get(0) != null) {
  8. inputStream.close();
  9. }
  10. }
  11. return var4;
  12. } catch (Throwable var9) {
  13. throw var9;
  14. }

}

  1. ### @Synchronized注解
  2. > synchronized是线程安全中一个重要的关键字,它是一种同步锁,主要用来保证在同一个时刻,只有一个线程可以执行某个方法或者某段代码块。一般使用synchronized去锁住代码块,而不是方法,因为锁住代码块效率更高。

public class RumenzSynchronized {

  1. private final Object readLock = new Object();
  2. @Synchronized
  3. public static void hello() {
  4. System.out.println("rumenz.com");
  5. }
  6. @Synchronized
  7. public int answerToLife() {
  8. return 110;
  9. }
  10. @Synchronized("readLock")
  11. public void foo() {
  12. System.out.println("入门小站");
  13. }

}

  1. // 等价于

public class RumenzSynchronized {
private static final Object $LOCK = new Object[0];
private final Object $lock = new Object[0];
private final Object readLock = new Object();

  1. public RumenzSynchronized() {
  2. }
  3. public static void hello() {
  4. synchronized($LOCK) {
  5. System.out.println("rumenz.com");
  6. }
  7. }
  8. public int answerToLife() {
  9. synchronized(this.$lock) {
  10. return 110;
  11. }
  12. }
  13. public void foo() {
  14. synchronized(this.readLock) {
  15. System.out.println("入门小站");
  16. }
  17. }

}

  1. ### @Builder注解
  2. > 用在类、构造器、方法上,为你提供复杂的builder APIs

@ToString
@Builder
public class RumenzBuilder {
private Integer id;
private String name;
}

  1. // 等价于

public class RumenzBuilder {
private Integer id;
private String name;

  1. RumenzBuilder(final Integer id, final String name) {
  2. this.id = id;
  3. this.name = name;
  4. }
  5. public static RumenzBuilder.RumenzBuilderBuilder builder() {
  6. return new RumenzBuilder.RumenzBuilderBuilder();
  7. }
  8. public String toString() {
  9. return "RumenzBuilder(id=" + this.id + ", name=" + this.name + ")";
  10. }
  11. public static class RumenzBuilderBuilder {
  12. private Integer id;
  13. private String name;
  14. RumenzBuilderBuilder() {
  15. }
  16. public RumenzBuilder.RumenzBuilderBuilder id(final Integer id) {
  17. this.id = id;
  18. return this;
  19. }
  20. public RumenzBuilder.RumenzBuilderBuilder name(final String name) {
  21. this.name = name;
  22. return this;
  23. }
  24. public RumenzBuilder build() {
  25. return new RumenzBuilder(this.id, this.name);
  26. }
  27. public String toString() {
  28. return "RumenzBuilder.RumenzBuilderBuilder(id=" + this.id + ", name=" + this.name + ")";
  29. }
  30. }

}

@GetMapping(“/index11”)
public String index11() {
RumenzBuilder rb=RumenzBuilder.builder().id(1).name(“入门小站”).build();
return rb.toString();
}
```

@SuperBuilder

当实体类有集成关系时,需要用@SuperBuilder,否则调用的.builder都会报错.

@Builder并不支持父类成员属性的构造,@SuperBuilder注解的出现,就是用来解决这个问题。

使用@Builder或@SuperBuilder注解时,不会默认创建空参构造函数,如果你有额外使用空参构造函数或全参构造函数的需求,需要在子类和父类都加上以下注解:

本小结源码地址:

介绍

  • 关注【入门小站】回复【1001】获取 linux常用命令速查手册
  • 关注【入门小站】回复【1003】获取 LeetCode题解【java语言实现】
  • 关注【入门小站】回复【1004】获取 Java基础核心总结
  • 关注【入门小站】回复【1009】获取 阿里巴巴Java开发手册
返回笔记列表
入门小站