lombok插件各个注解介绍

内容參考網址:https://blog.csdn.net/sunsfan/article/details/53542374

文章目录

lombok插件各个注解介绍

一、IDEA下载和配置lombok

打开IDEA,点击File 》 Settings…

lombok插件各个注解介绍
然后点击Plugins(插件),在Marketplace里面搜索 Lombok 下载即可。(这里我因为已经下载好了,所以他存放的位置是 Installed)
lombok插件各个注解介绍
下载完成后,我们只需要在我们的项目中引入依赖就可以使用啦!配置信息如下:

<dependencies>
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
    dependency>
dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-maven-pluginartifactId>
            <version>2.7.2version>
            <configuration>
                <excludes>
                    <exclude>
                        <groupId>org.projectlombokgroupId>
                        <artifactId>lombokartifactId>
                    exclude>
                excludes>
            configuration>
        plugin>
    plugins>
build>

之后我们就可以直接使用我们Lombok插件的各种注解啦!!!下面我们说一下各个注解的作用。

二、Lombok各注解介绍

lombok是一个可以帮助我们简化java代码编写的工具类,尤其是简化javabean的编写,即通过采用注解的方式,消除代码中的构造方法,getter/setter等代码,使我们写的类更加简洁。废话少说,我们直接来看看Lombok常用的一些注解。

2.1 @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();
}

再者,我们来个构造器的例子:

Employee(@NonNull String id, @NonNull String name,Integer age, Boolean gender, @NonNull Double salary){
    this.id = id;
    this.name = name;
    this.age = age;
    this.gender = gender;
    this.salary = salary;
}

該代碼就等價於:

Employee(@NonNull String id, @NonNull String name,Integer age, Boolean gender, @NonNull Double salary){
    if(id == null){
        throw new NullPointerException("id");
    }
    if(name == null){
        throw new NullPointerException("name ");
    }
    if(salary == null){
        throw new NullPointerException("salary");
    }
    this.id = id;
    this.name = name;
    this.age = age;
    this.gender = gender;
    this.salary = salary;
}

2.2 @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]);
     byte[] b = new byte[1024];
     while (true) {
       int r = in.read(b);
       if (r == -1) break;
       out.write(b, 0, r);
     }
 }

該代碼就等價於:

public static void main(String[] args) throws IOException {
     InputStream in = new FileInputStream(args[0]);
     try {
       OutputStream out = new FileOutputStream(args[1]);
       try {
         byte[] b = new byte[10000];
         while (true) {
           int r = in.read(b);
           if (r == -1) break;
           out.write(b, 0, r);
         }
       } finally {
         if (out != null) {
           out.close();
         }
       }
     } finally {
       if (in != null) {
         in.close();
       }
    }
}

2.3 @Getter/@Setter

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

public class Programmer{
    @Getter
    @Setter
    private String name;

    @Setter(AccessLevel.PROTECTED)
    private int age;

    @Getter(AccessLevel.PUBLIC)
    private String language;
}

該代碼就等價於:

public class Programmer{
    private String name;
    private int age;
    private String language;

    public void setName(String name){
        this.name = name;
    }

    public String getName(){
        return name;
    }

    protected void setAge(int age){
        this.age = age;
    }

    public String getLanguage(){
        return language;
    }
}

不過我們經常性的話,都是直接在類上面加,類似這樣:

@Getter
@Setter
public class Programmer{
    private String name;

    private int age;

    private String language;
}

該代碼就等價於:

public class Programmer{
    private String name;

    private int age;

    private String language;

    public void setName(String name){
        this.name = name;
    }

    public String getName(){
        return name;
    }

    public void setAge(int age){
        this.age = age;
    }

    public String getAge(){
        return age;
    }

    public void setLanguage(int language){
        this.language= language;
    }

    public String getLanguage(){
        return language;
    }
}

2.4 @ToString

这个也比较好理解,就是帮我们生成toString方法,帮我们输出所有的属性。直接代码走起:

@ToString
@Setter
@Getter
public class Student {
    private String id;
    private String name;
    private Integer age;
    private Map<String, Double> grade;
}

然後我們寫個測試方法來檢驗一下我們的成果:

public class StudentServiceTest {
    @Test
    public void testToString(){
        Student student = new Student();
        student.setId("1001");
        student.setName("小明");
        student.setAge(18);
        Map<String, Double> gradeMap = new HashMap<>();
        gradeMap.put("語文", 80.5d);
        gradeMap.put("數學", 99d);
        gradeMap.put("英語", 93.5d);
        student.setGrade(gradeMap);
        System.out.println(student);
    }
}

輸出結果如下:

lombok插件各个注解介绍

2.5 @EqualsAndHashCode

這個注解主要是幫我們生成三個方法:equals、hashcode、canEqual。其中用得比較多的可能就是我們的equals方法了,那麽他生成的equals方法都做了啥咧,其實也很簡單,就是調用它裏面所有屬性的equals方法,如果都爲true,那麽就返回true。舉個例子:

实体类代码如下:

@ToString
@Setter
@Getter
@EqualsAndHashCode
public class Student {
    private String id;
    private String name;
    private Integer age;
    private Map<String, Double> grade;
}

测试方法如下:

public void testEqualsAndHashCode(){
    Student student1 = new Student();
    student1.setId("1001");
    student1.setName("小明");
    student1.setAge(18);
    Map<String, Double> gradeMap1 = new HashMap<>();
    gradeMap1.put("語文", 80.5d);
    gradeMap1.put("數學", 99d);
    gradeMap1.put("英語", 93.5d);
    student1.setGrade(gradeMap1);

    Student student2 = new Student();
    student2.setId("1001");
    student2.setName("小明");
    student2.setAge(18);
    Map<String, Double> gradeMap2 = new HashMap<>();
    gradeMap2.put("語文", 80.5d);
    gradeMap2.put("數學", 99d);
    gradeMap2.put("英語", 93.5d);
    student2.setGrade(gradeMap2);
    System.out.println(student1.equals(student2));
}

输出结果:

lombok插件各个注解介绍

2.6 @NoArgsConstructor/@RequiredArgsConstructor /@AllArgsConstructor

Constructor翻译成中文其实就是构造器的意思。所以,我们的这三个注解(@NoArgsConstructor/@RequiredArgsConstructor /@AllArgsConstructor)其实就是生成三种构造器,分别是

  • NoArgsConstructor:无参构造器
  • RequiredArgsConstructor:為@NonNull注解和final修飾的成員變量生成特定参数构造方法。
  • AllArgsConstructor:全参构造器

第一个和第三个比较简单,假如现在我们的实体类如下:

@NoArgsConstructor
@AllArgsConstructor
public class Student {
    private String id;
    private String name;
    private Integer age;
    private Map<String, Double> grade;
}

該代碼就等價於:

public class Student {
    private String id;
    private String name;
    private Integer age;
    private Map<String, Double> grade;

    public Student(){}

    public Student(String id, String name, Integer age, Map<String, Double> grade) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.grade = grade;
    }
}

至於 @RequiredArgsConstructor 這個注解嘛,廢話少説,直接代碼開擼。

@ToString
@RequiredArgsConstructor(staticName = "getEasiestStudent")
public class Student {
    private final String id;
    @NonNull
    private String name;
    private Integer age;
    private Map<String, Double> grade;

}

等價於:

public class Student {
    private final String id;
    @NonNull
    private String name;
    private Integer age;
    private Map<String, Double> grade;

    public Student(String id, @NonNull String name){
        this.id = id;
        this.name = name;
    }

    public static Student getEasiestStudent(String id, String name){
        return new Student(id, name);
    }

}

如果我們@RequiredArgsConstructor不加 (staticName = “getEasiestStudent”) 這一串,直接用的話,寫的是 @RequiredArgsConstructor注解的話,那麽就只為所有的final字段還有@NonNull注解生成一個構造方法。

    public Student(String id, @NonNull String name){
        this.id = id;
        this.name = name;
    }

2.7 @Data

@Data這個注解好像是開發中最常用的,因爲他整合了我們前面的好幾個注解—— @Setter、@Getter、@ToString、@EqualsAndHashCode、@RequiredArgsConstructor。當然了,如果你想使用@RequiredArgsConstructor生成靜態構造方法的功能的話,你也可以使用 @Data(staticConstructor=”methodName”) 來生成你想要的構造方法。

2.8 @Value

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

2.9 @SneakyThrows

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

public class SneakyThrows implements Runnable {
    @SneakyThrows(UnsupportedEncodingException.class)
    public String utf8ToString(byte[] bytes) {
        return new String(bytes, "UTF-8");
    }

    @SneakyThrows
    public void run() {
        throw new Throwable();
    }
}

等價於:

public class SneakyThrows implements Runnable {
    @SneakyThrows(UnsupportedEncodingException.class)
    public String utf8ToString(byte[] bytes) {
        try{
            return new String(bytes, "UTF-8");
        }catch(UnsupportedEncodingException uee){
            throw Lombok.sneakyThrow(uee);
        }
    }

    @SneakyThrows
    public void run() {
        try{
            throw new Throwable();
        }catch(Throwable t){
            throw Lombok.sneakyThrow(t);
        }
    }
}

2.10 @Synchronized

这个注解用在类方法或者实例方法上,效果和synchronized关键字相同,区别在于锁对象不同,对于类方法和实例方法,synchronized关键字的锁对象分别是类的class对象和this对象,而@Synchronized得锁对象分别是 private static 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");
     }
   }
 }

2.11 @Log

这个注解用在类上,可以省去从日志工厂生成日志对象这一步,直接进行日志记录,具体注解根据日志工具的不同而不同,同时,可以在注解中使用topic来指定生成log对象时的类名。不同的日志注解总结如下(上面是注解,下面是实际作用):

@CommonsLog
private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);
@JBossLog
private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class);
@Log
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
@Log4j
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);
@Log4j2
private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
@Slf4j
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
@XSlf4j
private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);

举个例子吧:
比如我们现在使用的是Slf4j作为我们的日志配置工具,那么我们本来每一个Controller应该都要写一句 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(StudentController.class); 用於輸出我們具体的日志信息的,但是其实大可不必,我们只需要在我们的Controller类上面加上注释 @Slf4j 就可以了。
即,现有代码如下:

@RestController
@Slf4j
public class StudentController{

}

等價於:

@RestController
public class StudentController{
    private static final Logger log = LoggerFactory.getLogger(StudentController.class);

}

内容參考網址:https://blog.csdn.net/sunsfan/article/details/53542374

Original: https://blog.csdn.net/weixin_44741023/article/details/127745165
Author: Keeling1720
Title: lombok插件各个注解介绍

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/653839/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球