zoukankan      html  css  js  c++  java
  • Lombok快速上手(安装、使用与注解参数)

    Lombok插件安装与使用说明

    在实习中发现项目中IDE一直报检查错误,原来是使用了Lombok注解的黑科技,这里整理了一些日常编码中能遇到的所有关于它的使用详解,其实lombok项目的产生就是为了省去我们手动创建getter和setter方法等等一些基本组件代码的麻烦,它能够在我们编译源码的时候自动帮我们生成getter和setter方法。即它最终能够达到的效果是:在源码中没有getter和setter等组件方法,但是在编译生成的字节码文件中有getter和setter等组件方法。

    常见参数

    1. @Setter 注解在类或字段,注解在类时为所有字段生成setter方法,注解在字段上时只为该字段生成setter方法。
    2. @Getter 使用方法同上,区别在于生成的是getter方法。
    3. @ToString 注解在类,添加toString方法。
    4. @EqualsAndHashCode 注解在类,生成hashCode和equals方法。
    5. @NoArgsConstructor 注解在类,生成无参的构造方法。
    6. @RequiredArgsConstructor 注解在类,为类中需要特殊处理的字段生成构造方法,比如final和被@NonNull注解的字段。
    7. @AllArgsConstructor 注解在类,生成包含类中所有字段的构造方法。
    8. @Data 注解在类,为类的所有字段注解@ToString、@EqualsAndHashCode、@Getter的便捷方法,同时为所有非final字段注解@Setter。

    lombok的依赖于安装

    依赖管理

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.20</version>
    </dependency>
    

    IDEA插件的安装

    如果IDE没有安装插件的话会提示错误,而且不会有代码提示,所以IDE要安装插件

    1. 在IDEA插件里搜索lombok,安装,重启
    2. 直接官网下载插件,安装,这是链接
    3. 设置中启用annotation processors

    @Data小例子

    平时在使用时最常用@Data注解

    @Data可以很好地处理字段的泛型参数。 为了在为具有泛型的类构造对象时减少样板,可以使用staticConstructor参数来生成私有构造函数,以及返回新实例的静态方法。 这样,javac将推断变量名称。 因此,通过这样声明:@Data(staticConstructor =“of”)类Foo {private T x;}可以通过写入来创建Foo的新实例:Foo.of(5); 而不必写:new Foo (5);

    如果使用了@Data注解

    @Data public class DataExample {
      private final String name;
      @Setter(AccessLevel.PACKAGE) private int age;
      private double score;
      private String[] tags;
      
      @ToString(includeFieldNames=true)
      @Data(staticConstructor="of")
      public static class Exercise<T> {
        private final String name;
        private final T value;
      }
    }
    

    不加lombok注解的Pojo的写法

    public class DataExample {
      private final String name;
      private int age;
      private double score;
      private String[] tags;
      
      public DataExample(String name) {
        this.name = name;
      }
      
      public String getName() {
        return this.name;
      }
      
      void setAge(int age) {
        this.age = age;
      }
      
      public int getAge() {
        return this.age;
      }
      
      public void setScore(double score) {
        this.score = score;
      }
      
      public double getScore() {
        return this.score;
      }
      
      public String[] getTags() {
        return this.tags;
      }
      
      public void setTags(String[] tags) {
        this.tags = tags;
      }
      
      @Override public String toString() {
        return "DataExample(" + this.getName() + ", " + this.getAge() + ", " + this.getScore() + ", " + Arrays.deepToString(this.getTags()) + ")";
      }
      
      protected boolean canEqual(Object other) {
        return other instanceof DataExample;
      }
      
      @Override public boolean equals(Object o) {
        if (o == this) return true;
        if (!(o instanceof DataExample)) return false;
        DataExample other = (DataExample) o;
        if (!other.canEqual((Object)this)) return false;
        if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false;
        if (this.getAge() != other.getAge()) return false;
        if (Double.compare(this.getScore(), other.getScore()) != 0) return false;
        if (!Arrays.deepEquals(this.getTags(), other.getTags())) return false;
        return true;
      }
      
      @Override public int hashCode() {
        final int PRIME = 59;
        int result = 1;
        final long temp1 = Double.doubleToLongBits(this.getScore());
        result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode());
        result = (result*PRIME) + this.getAge();
        result = (result*PRIME) + (int)(temp1 ^ (temp1 >>> 32));
        result = (result*PRIME) + Arrays.deepHashCode(this.getTags());
        return result;
      }
      
      public static class Exercise<T> {
        private final String name;
        private final T value;
        
        private Exercise(String name, T value) {
          this.name = name;
          this.value = value;
        }
        
        //可以看到这里自动生成了of方法
        public static <T> Exercise<T> of(String name, T value) {
          return new Exercise<T>(name, value);
        }
        
        public String getName() {
          return this.name;
        }
        
        public T getValue() {
          return this.value;
        }
        
        @Override public String toString() {
          return "Exercise(name=" + this.getName() + ", value=" + this.getValue() + ")";
        }
        
        protected boolean canEqual(Object other) {
          return other instanceof Exercise;
        }
        
        @Override public boolean equals(Object o) {
          if (o == this) return true;
          if (!(o instanceof Exercise)) return false;
          Exercise<?> other = (Exercise<?>) o;
          if (!other.canEqual((Object)this)) return false;
          if (this.getName() == null ? other.getValue() != null : !this.getName().equals(other.getName())) return false;
          if (this.getValue() == null ? other.getValue() != null : !this.getValue().equals(other.getValue())) return false;
          return true;
        }
        
        @Override public int hashCode() {
          final int PRIME = 59;
          int result = 1;
          result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode());
          result = (result*PRIME) + (this.getValue() == null ? 43 : this.getValue().hashCode());
          return result;
        }
      }
    }
    

    扩展@ToString

    任何类定义都可以用@ToString注释,让lombok生成toString()方法的实现。默认情况下,它会按顺序打印类名以及每个字段,并以逗号分隔。

    通过将includeFieldNames参数设置为true,您可以为toString()方法的输出更详细(但也有一些长度)。这是默认的

    默认情况下,将打印所有非静态字段。如果要跳过某些字段,可以使用@ ToString.Exclude注释这些字段。或者,您可以使用@ToString(onlyExplicitlyIncluded = true)准确指定要使用的字段,然后使用@ ToString.Include标记要包含的每个字段。

    通过将callSuper设置为true,可以将toString的超类实现的输出包含到输出中。但是java.lang.Object中toString()的默认实现几乎毫无意义,因此除非扩展另一个类,否则不要这样做。

    还可以在toString中包含方法调用的输出。只能包含不带参数的实例(非静态)方法。为此,请使用@ToString.Include标记方法。

    可以使用@ToString.Include(name =“some other name”)更改用于标识成员的名称,并且可以通过@ToString.Include(rank = -1)更改成员的打印顺序。没有等级的成员被认为具有等级0,更高等级的成员被首先打印,并且相同等级的成员以它们在源文件中出现的相同顺序被打印。

    ToString小例子:

    加注解:

    @ToString
    public class ToStringExample {
      private static final int STATIC_VAR = 10;
      private String name;
      private Shape shape = new Square(5, 10);
      private String[] tags;
      @ToString.Exclude private int id;
      
      public String getName() {
        return this.name;
      }
      
      @ToString(callSuper=true, includeFieldNames=true)
      public static class Square extends Shape {
        private final int width, height;
        
        public Square(int width, int height) {
          this.width = width;
          this.height = height;
        }
      }
    }
    

    等效于:

    public class ToStringExample {
      private static final int STATIC_VAR = 10;
      private String name;
      private Shape shape = new Square(5, 10);
      private String[] tags;
      private int id;
      
      public String getName() {
        return this.getName();
      }
      
      public static class Square extends Shape {
        private final int width, height;
        
        public Square(int width, int height) {
          this.width = width;
          this.height = height;
        }
        
        @Override public String toString() {
          return "Square(super=" + super.toString() + ", width=" + this.width + ", height=" + this.height + ")";
        }
      }
      
      @Override public String toString() {
        return "ToStringExample(" + this.getName() + ", " + this.shape + ", " + Arrays.deepToString(this.tags) + ")";
      }
    }
    

    构造器注解扩展

    @NoArgsConstructor

    此注释主要与@Data或生成注释的其他构造函数组合使用。

    @NoArgsConstructor将生成一个没有参数的构造函数。如果这是不可能的(因为最终字段),将导致编译器错误,除非使用@NoArgsConstructor(force = true),然后使用0 / false / null初始化所有final字段。对于具有约束的字段,例如@NonNull字段,不会生成任何检查,因此请注意,在稍后正确初始化这些字段之前,通常不会满足这些约束。某些java构造(例如hibernate和Service Provider Interface)需要no-args构造函数。

    @RequiredArgsConstructor

    @RequiredArgsConstructor为每个需要特殊处理的字段生成一个带有1个参数的构造函数。所有未初始化的final字段都会获得一个参数,以及标记为@NonNull的任何字段,这些字段在声明它们时未初始化。对于标有@NonNull的字段,还会生成显式空检查。如果用于标记为@NonNull的字段的任何参数包含null,则构造函数将抛出NullPointerException。参数的顺序与字段在类中的显示顺序相匹配。

    @AllArgsConstructor

    @AllArgsConstructor为类中的每个字段生成一个带有1个参数的构造函数。标有@NonNull的字段会导致对这些参数进行空检查。

    这些注释中的每一个都允许使用替代形式,其中生成的构造函数始终是私有的,并且生成包围私有构造函数的附加静态工厂方法。通过为注释提供staticName值来启用此模式,如下所示:@RequiredArgsConstructor(staticName =“of”)。与普通构造函数不同,这种静态工厂方法将推断泛型。这意味着您的API用户可以编写MapEntry.of(“foo”,5)而不是更长的新MapEntry <String,Integer>(“foo”,5)。

    与大多数其他lombok注释不同,显式构造函数的存在不会阻止这些注解生成自己的构造函数。这意味着可以编写自己的专用构造函数,并让lombok生成样板文件。

    注意:如果出现冲突(自定义的一个构造函数最终使用与lombok生成的构造函数相同),则会发生编译器错误

    @Log及其他日志注解

    就是简化了生成log的代码,直接看例子

    @Log
    public class LogExample {
      
      public static void main(String... args) {
        log.severe("Something's wrong here");
      }
    }
    
    @Slf4j
    public class LogExampleOther {
      
      public static void main(String... args) {
        log.error("Something else is wrong here");
      }
    }
    
    @CommonsLog(topic="CounterLog")
    public class LogExampleCategory {
    
      public static void main(String... args) {
        log.error("Calling the 'CounterLog' with a message");
      }
    }
    

    等效于:

    public class LogExample {
      private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
      
      public static void main(String... args) {
        log.severe("Something's wrong here");
      }
    }
    
    public class LogExampleOther {
      private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExampleOther.class);
      
      public static void main(String... args) {
        log.error("Something else is wrong here");
      }
    }
    
    public class LogExampleCategory {
      private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog("CounterLog");
    
      public static void main(String... args) {
        log.error("Calling the 'CounterLog' with a message");
      }
    }
    

    资料链接

    想要更详细的了解Lombok,推荐查看它的github来阅读更多的使用特性

    Lombok的gitHub链接

  • 相关阅读:
    C语言-if语句
    C语言-表达式
    C语言-基础
    Java for LeetCode 187 Repeated DNA Sequences
    Java for LeetCode 179 Largest Number
    Java for LeetCode 174 Dungeon Game
    Java for LeetCode 173 Binary Search Tree Iterator
    Java for LeetCode 172 Factorial Trailing Zeroes
    Java for LeetCode 171 Excel Sheet Column Number
    Java for LeetCode 169 Majority Element
  • 原文地址:https://www.cnblogs.com/keeya/p/9929617.html
Copyright © 2011-2022 走看看