lombok

前言

  • lombok的注解都是基于编译期。

@UtilityClass

  • 编译后添加私有无参构造方法并在方法中抛出异常
private A() {
    throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}
  • 编译后方法都加上了static关键字(privatepublic都加上)
public static void test() {
    System.out.println("xxx");
}

private static void method() {
        System.out.println("xxx");
}
  • 如果类有任何构造方法,无法再添加UtilityClass,反之,如果加了UtilityClass,也无法再添加构造方法(二者只能取其一,即使使用AllArgsConstructor等注解也不行)

  • 如果有属性,建议手动写static,不要依赖于UtilityClass,具体暂时未测试。

@NonNull

  • 编译后对于方法中加了NonNull的参数以抛异常方式进行NPE校验

    • 编译前

      private String wrapper(@NonNull Integer generatorId) {
          generatorId++;
          return String.format("%04d", generatorId);
      }
      
    • 编译后

      private String wrapper(@NonNull Integer generatorId) {
         if (generatorId == null) {
             throw new NullPointerException("generatorId is marked non-null but is null");
         } else {
             generatorId = generatorId + 1;
             return String.format("%04d", generatorId);
         }
      }
      

@NonNull和@Nullable

  • org.springframework.lang包下有两个注解 NonNull,Nullable都属于提示注解,前者提示不能为null,后者提示可以为null,无任何编译效果,属于给写代码的人看的

@RequiredArgsConstructor

  • 编译后对类中加了@NonNull注解或者final类型的字段生成构造方法,同时默认的无参构造方法不会保留

  • 分别准备以下四个类,测试@RequiredArgsConstructor注解的作用

    • 编译前

      @RequiredArgsConstructor
      public class A {
      }
      
      
      @RequiredArgsConstructor
      public class B {
          private String msg;
      }
      
      @RequiredArgsConstructor
      public class C {
          private final String msg;
      }
      
      @RequiredArgsConstructor
      public class D {
          @NonNull
          private String msg;
      }
      
    • 编译后

      public class A {
          public A() {
          }
      }
      
      public class B {
          private String msg;
      
          public B() {
          }
      }
      
      
      public class C {
          private final String msg;
      
          public C(final String msg) {
              this.msg = msg;
          }
      }
      
      public class D {
          @NonNull
          private String msg;
      
          public D(@NonNull final String msg) {
              if (msg == null) {
                  throw new NullPointerException("msg is marked non-null but is null");
              } else {
                  this.msg = msg;
              }
          }
      }
      
  • 加了staticName后会将构造方法置为私有,同时生成一个静态的以staticName后面的属性为方法名的方法,来调用私有的构造的构造

    • 编译前

      @RequiredArgsConstructor(staticName = "of")
      public class D {
          @NonNull
          private String msg;
      }
      
    • 编译后

      public class D {
          @NonNull
          private String msg;
      
          private D(@NonNull final String msg) {
              if (msg == null) {
                  throw new NullPointerException("msg is marked non-null but is null");
              } else {
                  this.msg = msg;
              }
          }
      
          public static D of(@NonNull final String msg) {
              return new D(msg);
          }
      }
      

@NoArgsConstructor

  • 生成无参的构造方法

@AllArgsConstructor

  • 生成全部参数的构造方法

@Getter

  • 生成get方法

@Setter

  • 生成set方法
  • final类型的字段不会生成set方法

@Slf4j

  • slf4j日志

    private static final Logger log = LoggerFactory.getLogger(A.class);
    

@EqualsAndHashCode

  • 此注解会生成equals(Object other) 和 hashCode()方法
  • 它默认使用非静态,非瞬态的属性
  • 可通过参数exclude排除一些属性
  • 可通过参数of指定仅使用哪些属性
  • 它默认仅使用该类中定义的属性且不调用父类的方法
  • 可通过callSuper=true解决上一点问题。让其生成的方法中调用父类的方法

@Data

  • @Data相当于@Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode这5个注解的合集
  • 当使用@Data注解时,则有了@EqualsAndHashCode注解,那么就会在此类中存在equals(Object other)hashCode()方法,且不会使用父类的属性,这就导致了可能的问题解决方法:使用在使用@Data时同时加上@EqualsAndHashCode(callSuper=true)

@Builder

​ 非常推荐的一种构建值对象的方式。缺点就是父类的属性不能产于builder,不要轻易使用

  • 编译前

    @Builder
    public class Demo {
        private final int finalVal = 10;
    
        private String name;
        private int age;
    }
    
  • 编译后

    public class Demo {
        private final int finalVal = 10;
        private String name;
        private int age;
    
        Demo(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public static Demo.DemoBuilder builder() {
            return new Demo.DemoBuilder();
        }
    
        public static class DemoBuilder {
            private String name;
            private int age;
    
            DemoBuilder() {
            }
    
            public Demo.DemoBuilder name(String name) {
                this.name = name;
                return this;
            }
    
            public Demo.DemoBuilder age(int age) {
                this.age = age;
                return this;
            }
    
            public Demo build() {
                return new Demo(this.name, this.age);
            }
    
            public String toString() {
                String var10000 = this.name;
                return this.age;
            }
        }
    }
    
  • 使用

     public static void main(String[] args) {
            Demo demo = Demo.builder().name("aa").age(10).build();
            System.out.println(demo); 
    }
    
原文地址:https://www.cnblogs.com/linqing001/p/14107933.html