• lombok总结


    特性

    val/var

    val可以作为局部变量声明的类型,而不必编写实际类型。val注解将从初始化程序表达式中推断类型。局部变量也将成为最终变量。此功能仅适用于局部变量和foreach循环,不适用于字段(实体类的成员变量)。同时,初始化表达式是必需的。
    var和val的差别在于,val修饰的局部变量没有被标记为final。

    一般不建议使用。缺点:

    1、IDEA对 变量 final的识别问题

    2、val和var是根据初始化表达式的类型去生成变量类型的,变量是具体类的类型,而不是接口或抽象类。

    @NonNull

    用在成员方法或者构造方法的参数前面,会自动产生一个关于此参数的非空检查,如果参数为空,则抛出一个空指针异常

    //成员方法参数加上@NonNull注解
    public String getName(@NonNull Person p){
        return p.getName();
    }
    //实际效果相当于:
    public String getName(@NonNull Person p){
        if(p==null){
            throw new NullPointerException("person");
        }
        return p.getName();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    @Cleanup

    这个注解用在变量前面,可以保证此变量代表的资源会被自动关闭,默认是调用资源的close()方法,如果该资源有其它关闭方法,可使用@Cleanup(“methodName”)来指定要调用的方法

    public static void main(String[] args) throws IOException {
         @Cleanup InputStream in = new FileInputStream(args[0]);
         @Cleanup OutputStream out = new FileOutputStream(args[1]);
        ... ...
     }
    //相当于
    
    public static void main(String[] args) throws IOException {
         InputStream in = new FileInputStream(args[0]);
         try {
           OutputStream out = new FileOutputStream(args[1]);
           try {
             
             ... ...
           } finally {
             if (out != null) {
               out.close();
             }
           }
         } finally {
           if (in != null) {
             in.close();
           }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    @Getter/@Setter

    为成员变量生成对应的get和set方法,同时还可以为生成的方法指定访问修饰符

    @Target({ElementType.FIELD, ElementType.TYPE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Getter {
      //指定访问控制:PUBLIC, PROTECTED, PACKAGE, and PRIVATE
    	lombok.AccessLevel value() default lombok.AccessLevel.PUBLIC;
    
    	AnyAnnotation[] onMethod() default {};
    	//懒加载
    	boolean lazy() default false;
    
    	@Deprecated
    	@Retention(RetentionPolicy.SOURCE)
    	@Target({})
    	@interface AnyAnnotation {}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    AccessLevel.NONE可以重写@Getter, @Setteror@Data 的行为。

    public class Programmer{
        @Getter
        @Setter
        private String name;
    
        @Setter(AccessLevel.PROTECTED)
        private int age;
    
        @Getter(AccessLevel.PUBLIC)
        private String language;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    @ToString

    No need to start a debugger to see your fields: Just let lombok generate a toString for you!

    public @interface ToString {
      //是否包含字段名称
    	boolean includeFieldNames() default true;
    
      /**排除的字段名称,将废弃,使用Exclude
      */
    	String[] exclude() default {};
    	
    	/** 指示使用那些字段 生成toString。将废弃,使用Include。
    	 */
    	String[] of() default {};
    	
      //是否包含父类的字段
    	boolean callSuper() default false;
    	
      //是否直接使用字段的值。
    	boolean doNotUseGetters() default false;
    
      //是否仅使用明确标识了 @ToString.Include的字段
    	boolean onlyExplicitlyIncluded() default false;
    
    	public @interface Exclude {}
    	
    	/** 配置toString的返回值,放在方法上,则以方法的返回值作为输出。
    	 */
    	public @interface Include {
    		int rank() default 0;
    		
    		String name() default "";
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    @EqualsAndHashCode

    重写equals(Object other)hashCode()方法。字段控制类似于@ToString

    @NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor

    这三个注解都是用在类上的,第一个和第三个是为该类产生无参的构造方法和包含所有参数的构造方法

    第二个注解则使用类中所有带有@NonNull注解的或者带有final修饰的成员变量生成对应的构造方法

    成员变量都是非静态的,另外,如果类中含有final修饰的成员变量,是无法使用@NoArgsConstructor注解的。
    三个注解都可以指定生成的构造方法的访问权限,同时,第二个注解还可以用@RequiredArgsConstructor(staticName=”methodName”)的形式生成一个指定名称的静态方法,返回一个调用相应的构造方法产生的对象

    @Data/@Value

    @Data注解综合了@Getter/@Setter@ToString@EqualsAndHashCode@RequiredArgsConstructor 注解,其中@RequiredArgsConstructor使用了类中的带有@NonNull注解的或者final修饰的成员变量,它可以使用@Data(staticConstructor=”methodName”)来生成一个静态方法,返回一个调用相应的构造方法产生的对象。

    @Value注解和@Data类似,区别在于它会把所有成员变量默认定义为private final修饰,并且不会生成set方法。

    @Builder

    创建Builder。

    public @interface Builder {
    	/**
    	 *  标记一个字段使用默认值,
    	 */
    	@Target(FIELD)
    	@Retention(SOURCE)
    	public @interface Default {}
    
    	/** 创建Builder的方法的名称 */
    	String builderMethodName() default "builder";
    	
    	/** buidler实例的方法的名称 */
    	String buildMethodName() default "build";
    
    	String builderClassName() default "";
    	
    	// 使用toBuilder可以实现以一个实例为基础继续创建一个对象。(也就是重用原来对象的值)
    	boolean toBuilder() default false;
    	
    	AccessLevel access() default lombok.AccessLevel.PUBLIC;
    	
      /** 不使用默认生成的函数名*/
    	@Target({FIELD, PARAMETER})
    	@Retention(SOURCE)
    	public @interface ObtainVia {
    		String field() default "";
    		String method() default "";
    		boolean isStatic() default false;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    在对实体对象进行操作时,往往会存在对某些实体对象的某个字段进行二次赋值,这个时候就会用到toBuilder属性。但是,这会创建一个新的对象,而不是原来的对象,原来的对象属性是不可变的

    @Default

    public class RelationalCriteria{}
    		@NonNull
        @Builder.Default
        private Integer id = 0;
        @NonNull
        @Builder.Default
        private Integer parentId = -1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    编译:

       public class RelationalCriteria{}
        @NonNull
        private Integer id;
        @NonNull
        private Integer parentId;
    
    		//默认值获取方法
    		private static Integer $default$id() {
            return 0;
        }
    
        private static Integer $default$parentId() {
            return -1;
        }
    }
    
      public static class RelationalCriteriaBuilder {
            private RelationalOperatorType operator;
            private boolean id$set;     //
            private Integer id$value;
            private boolean parentId$set;  //加Default注解的
            private Integer parentId$value;
            private String code;
            private PropertyDataType propertyDataType;
            private Object operand;
        
           
           public RelationalCriteria.RelationalCriteriaBuilder id(@NonNull Integer id) {
                if (id == null) {
                    throw new NullPointerException("id is marked non-null but is null");
                } else {
                    this.id$value = id;
                    this.id$set = true;    //加Default注解的
                    return this;
                }
            }
    
            public RelationalCriteria.RelationalCriteriaBuilder parentId(@NonNull Integer parentId) {
                if (parentId == null) {
                    throw new NullPointerException("parentId is marked non-null but is null");
                } else {
                    this.parentId$value = parentId;
                    this.parentId$set = true;
                    return this;
                }
            }    
        
            public RelationalCriteria build() {
                Integer id$value = this.id$value;
                if (!this.id$set) {      //加Default注解的
                    id$value = RelationalCriteria.$default$id();
                }
    
                Integer parentId$value = this.parentId$value;
                if (!this.parentId$set) {   //加Default注解的
                    parentId$value = RelationalCriteria.$default$parentId();
                }
    
                return new RelationalCriteria(this.operator, id$value, parentId$value, this.code, this.propertyDataType, this.operand);
            }    
       }     
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    @ObtainVia

    生成 toBuilder()方法时,起作用。

    @Builder(toBuilder = true)
    public class RelationalCriteria implements ICriteriaNode {
        @Getter
        @NonNull
        @Builder.ObtainVia(method = "calculateFoo")  //定义的方法。
        private Object operand;
        ... ... 
            private Object calculateFoo()
        {
            return "xxx";
        }
        
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    编译:

        public RelationalCriteria.RelationalCriteriaBuilder toBuilder() {
            return (new RelationalCriteria.RelationalCriteriaBuilder()).operator(this.operator).id(this.id).parentId(this.parentId).code(this.code).propertyDataType(this.propertyDataType)
              //设置operand时,调用calculateFoo 方法
              .operand(this.calculateFoo());
        }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    @Singular

    用于配置@Builder怎么处理集合类型的字段。为集合类型的参数或字段生成一种特殊的方法。 它采用修改列表中一个元素而不是整个列表的方式,可以是增加一个元素,也可以是删除一个元素。

    在使用@Singular注释注释一个集合字段(使用@Builder注释类),lombok会将该构建器节点视为一个集合,并生成两个adder方法而不是setter方法。

    • 一个向集合添加单个元素
    • 一个将另一个集合的所有元素添加到集合中

    将不生成仅设置集合(替换已添加的任何内容)的setter。 还生成了clear方法。 这些singular构建器相对而言是有些复杂的,主要是来保证以下特性:

    在调用build()时,生成的集合将是不可变的。

    在调用build()之后调用其中一个adder方法或clear方法不会修改任何已经生成的对象。如果对集合修改之后,再调用build(),则会创建一个基于上一个对象创建的对象实体。

    生成的集合将被压缩到最小的可行格式,同时保持高效。

    @Singular只能应用于lombok已知的集合类型。目前,支持的类型有:

    java.util:

    • Iterable, Collection, 和List (一般情况下,由压缩的不可修改的ArrayList支持).
    • Set, SortedSet, and NavigableSet (一般情况下,生成可变大小不可修改的HashSet或者TreeSet).
    • Map, SortedMap, and NavigableMap (一般情况下,生成可变大小不可修改的HashMap或者TreeMap).

    Guava’s com.google.common.collect:

    • ImmutableCollection and ImmutableList
    • ImmutableSet and ImmutableSortedSet
    • ImmutableMap, ImmutableBiMap, and ImmutableSortedMap
    • ImmutableTable
    @Builder
    public class User {
        private final Integer id;
        private final String zipCode = "123456";
        private String username;
        private String password;
        @Singular
        private List<String> hobbies;
    }
     
    // 编译后:
    public class User {
        private final Integer id;
        private final String zipCode = "123456";
        private String username;
        private String password;
        private List<String> hobbies;
        User(Integer id, String username, String password, List<String> hobbies) {
            this.id = id; this.username = username;
            this.password = password; this.hobbies = hobbies;
        }
     
        public static User.UserBuilder builder() {return new User.UserBuilder();}
     
        public static class UserBuilder {
            private Integer id;
            private String username;
            private String password;
            private ArrayList<String> hobbies;
            UserBuilder() {}
            public User.UserBuilder id(Integer id) { this.id = id; return this; }
            public User.UserBuilder username(String username) { this.username = username; return this; }
            public User.UserBuilder password(String password) { this.password = password; return this; }
     
            public User.UserBuilder hobby(String hobby) {
                if (this.hobbies == null) {
                    this.hobbies = new ArrayList();
                }
                this.hobbies.add(hobby);
                return this;
            }
     
            public User.UserBuilder hobbies(Collection<? extends String> hobbies) {
                if (this.hobbies == null) {
                    this.hobbies = new ArrayList();
                }
                this.hobbies.addAll(hobbies);
                return this;
            }
     
            public User.UserBuilder clearHobbies() {
                if (this.hobbies != null) {
                    this.hobbies.clear();
                }
                return this;
            }
     
            public User build() {
                List hobbies;
                switch(this.hobbies == null ? 0 : this.hobbies.size()) {
                case 0:
                    hobbies = Collections.emptyList();
                    break;
                case 1:
                    hobbies = Collections.singletonList(this.hobbies.get(0));
                    break;
                default:
                    hobbies = Collections.unmodifiableList(new ArrayList(this.hobbies));
                }
                return new User(this.id, this.username, this.password, hobbies);
            }
            public String toString() {
                return "User.UserBuilder(id=" + this.id + ", username=" + this.username + ", password=" + this.password + ", hobbies=" + this.hobbies + ")";
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76

    @SneakyThrows

    这个注解用在方法上,可以将方法中的代码用try-catch语句包裹起来,捕获异常并在catch中用Lombok.sneakyThrow(e)把异常抛出,可以使用@SneakyThrows(Exception.class)的形式指定抛出哪种异常。

    @Synchronized

    这个注解用在类方法或者实例方法上,效果和synchronized关键字相同,区别在于锁对象不同,对于类方法和实例方法,synchronized关键字的锁对象分别是类的class对象和this对象,而@Synchronized得锁对象分别是私有静态final对象lock

    public class Synchronized {
        private final Object readLock = new Object();
    
        @Synchronized
        public static void hello() {
            System.out.println("world");
        }
    
        @Synchronized
        public int answerToLife() {
            return 42;
        }
    
        @Synchronized("readLock")
        public void foo() {
            System.out.println("bar");
        }
    }
    
    //相当于
    public class Synchronized {
       private static final Object $LOCK = new Object[0];
       private final Object $lock = new Object[0];
       private final Object readLock = new Object();
    
       public static void hello() {
         synchronized($LOCK) {
           System.out.println("world");
         }
       }
    
       public int answerToLife() {
         synchronized($lock) {
           return 42;
         }
       }
    
       public void foo() {
         synchronized(readLock) {
           System.out.println("bar");
         }
       }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    @With

    用于仅改变一个字段的值的情况下的对象复制,生成一个新对象。可以加载类上,也可以加在字段上。加在类上相当于给所有字段 @With。表示可以通过此生成的方法修改字段的值。未加@With的则不能。

    //生成的代码
    public Test withName(final String name) {
        return this.name == name ? this : new Test(name, this.password, this.age);
    }
    
    public Test withPassword(final String password) {
        return this.password == password ? this : new Test(this.name, password, this.age);
    }
    
    public Test withAge(final String age) {
        return this.age == age ? this : new Test(this.name, this.password, age);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    public @interface With {
    	AccessLevel value() default AccessLevel.PUBLIC;
    	
    	/**
    	 * 放在方法上的注解
    	 */
    	AnyAnnotation[] onMethod() default {};
    	
    	/**
    	 * 放在参数上的注解
    	 */
    	AnyAnnotation[] onParam() default {};
    
    	@Deprecated
    	@Retention(RetentionPolicy.SOURCE)
    	@Target({})
    	@interface AnyAnnotation {}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    @Log

    experimental

    试验性质的,以后可能会 采用或者弃用。

    @Accessors

    可加在类或字段上,用于配置gettersetter方法的生成结果。

    @Target({ElementType.TYPE, ElementType.FIELD})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Accessors {
    	//true: getter,setter方法没有get,set前缀,而是 以字段名作为方法名重载2个方法。
    	boolean fluent() default false;
    	
    	//true:setter返回值不再为void,而是this。
    	boolean chain() default false;
    	
    	/**用于生成getter和setter方法的字段名会忽视指定前缀(遵守驼峰命名)。
    	* 仅在指定prefix之后的字符不是小写字符的情况。
    	 */
    	String[] prefix() default {};
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    生成代码

    //fluent =true, 生成的getter和setter方法如下
    	public Long getId() {}
    	public void setId(Long id) {}
    	public String getName() {}
    	public void setName(String name) {}
    
    //chain = true
        public User setName(String name) {
          ...
           return this;
        }
    //@Accessors(prefix = "p")
    	private String pName;
    	public String getName() {}
    	public void setName(String name) {}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    @ExtensionMethod

    给指定类扩展方法,类似于C#中的扩展函数

    @FieldDefaults

    给每个字段加访问修饰符或final。

    @Delegate

    @UtilityClass

    指定为工具类

    @FieldNameConstants

    @StandardException

    定义标准Exception的几个方法

    参考

    https://projectlombok.org/features/all

    问题

    @AllArgsConstructor导致jackson 解析错误

    com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of  (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
    
    • 1

    序列化需要无参构造,加上lombok注解@AllArgsConstructor就没有无参构造,有其他所有参数的构造方法,所以这时候要加个@NoArgsConstructor注解,表示加无参构造。

  • 相关阅读:
    如何进行复盘?
    Torch截断一部分后是否能梯度回传
    Vue前端开发:事件传参
    ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
    Wireshark流量分析例题
    git 拉取tag分支
    【技术分享】基于编码注入的对抗性NLP攻击
    在antd-table新增索引列
    【编程题】【Scratch三级】2021.12跳高比赛
    VS 管理员权限问题
  • 原文地址:https://blog.csdn.net/demon7552003/article/details/127464766