一篇学会lombok常用注解的基本使用

lombok的学习

基本概念
  • Lombok项目其实就是一个java库,它可以自动插入到编辑器和构建工具中,增强java的性能。以后你只需要一些简单的注解,就可以再也不用在类中反复去写get、equals等方法。
  • 使用lombok可以简化开发的代码量,减少书写的set、get方法以及一些基本的校验
参考
  • 官方注解文档:https://projectlombok.org/features/
    • https://projectlombok.org/features/experimental/
  • 官方API文档:https://projectlombok.org/api/
@NonNull
  • 可以使用在类的构造方法的参数上,或者属性的set方法中的参数上
属性set方法上:
    public void setName(@NonNull String name) {
        this.name = name;
    }
    // 相当于
    public void setName(@NonNull String name) {
        if (name == null) {
          throw new NullPointerException("name is marked @NonNull but is null");
        this.name = name;
    }
构造方法上
    public Entity1(@NonNull String attribute1,@NonNull String attribute2) throws Exception {
        this.attribute1 = attribute1;
        this.attribute2 = attribute2;
    }
    // 相当于
    public Entity1(String attribute1,@NonNull String attribute2) throws Exception {
        if (attribute2 == null) {
          throw new NullPointerException("attribute2 is marked @NonNull but is null");
        this.attribute1 = attribute1;
        this.attribute2 = attribute2;
    }
@Setter和@Getter
  • 在类中的属性上使用,可以当成属性存在set和get方法
  • 这两个注解可以通过AccessLevel来设置访问权限
public class Entity2 {
    @Setter
    @Getter
    private String attribute1;
    @Setter(AccessLevel.PRIVATE)
    private String attribute2;
}
@Cleanup
  • 这个注解用在变量前面,可以保证此变量对应的资源回自动关闭,默认调用资源的close()方法
  • 如果该资源有其他关闭方法,可以使用@Cleanup(“methondName”)来指定要调用的方法
import lombok.Cleanup;

import java.io.*;

public class test3 {
    public static void main(String[] args) throws IOException {
        FileInputStream fileInputStream = methond1();
        System.out.println(fileInputStream.available());
    }

    private static FileInputStream methond1() throws IOException {
        @Cleanup
        FileInputStream writer = new FileInputStream("E:\\test.txt");
        System.out.println(writer.available());
        return writer;
    }
}
// 结果:
// 12
// Exception in thread "main" java.io.IOException: Stream Closed
@ToString
  • 在类名上面使用,可以标识类已经重写了toString方法
@EqualsAndHashCode
  • 在类名上面使用,可以标识类已经重写了equals方法和HashCode方法
@NoArgsConstructor、@RequiredArgsConstructor和@AllArgsConstructor
  • 这三个注解用于自动生成构造方法
  • @NoArgsConstructor
    • 用于生成一个无参的默认构造方法。它可以自动为类生成一个无参的构造方法,无需手动编写。
  • @RequiredArgsConstructor
    • 用于生成构造方法,只包含带有final或@NonNull注解的成员变量作为参数。它可以自动为这些成员变量生成对应的构造方法。
  • @AllArgsConstructor
    • 用于生成一个包含所有非静态成员变量的构造方法。它可以自动为类生成一个包含所有成员变量的构造方法。
import lombok.AllArgsConstructor;

@AllArgsConstructor
public class MyClass {
    private String name;
    private int age;
    // 其他成员和方法
}
@Data
  • 注解在类上,会为类的所有属性自动生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。
@Value
  • 注解在类上,会为类的所有属性自动生成getter、equals、canEqual、hashCode、toString方法
  • 由于没有生成setter方法,所以一旦对象创建后,其字段值就无法修改。
  • 与@Date的区别:
    • 会把所有成员变量默认定义为private final修饰,并且不会生成set方法。
    • @Data 适用于需要可变性的类,它会生成 getter 和 setter 方法;@Value 适用于不可变性的类,它只生成 getter 方法,没有 setter 方法。这对于保证对象的不可变性是有益的。
@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 {
  public String utf8ToString(byte[] bytes) {
    try{
      return new String(bytes, "UTF-8");
    }catch(UnsupportedEncodingException uee){
      throw Lombok.sneakyThrow(uee);
    }
  }

  public void run() {
    try{
      throw new Throwable();
    }catch(Throwable t){
      throw Lombok.sneakyThrow(t);
    }
  }
}
@Synchronized
  • @Synchronized这个注解用在类方法或者实例方法上,效果和synchronized关键字相同,区别在于锁对象不同,对于类方法和实例方法,synchronized关键字的锁对象分别是类的class对象和this对象,而@Synchronized得锁对象分别是私有静态final对象LOCK和私有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");
     }
   }
 }
@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);
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ExampleClass {
    public void doSomething() {
        log.info("This is an info log message.");
        log.error("This is an error log message.");
    }
}
注解的缺点
  • 高入侵性
    • Lombok插件的使用,要求开发者一定要在IDE中安装对应的插件。不仅自己要安装,任何和你协同开发的人都要安装。如果有谁未安装插件的话,使用IDE打开一个基于Lombok的项目的话会提示找不到方法等错误,导致项目编译失败。更重要的是,如果我们定义的一个jar包中使用了Lombok,那么就要求所有依赖这个jar包的所有应用都必须安装插件,这种侵入性是很高的。
  • 代码可调试性降低
    • Lombok确实可以帮忙减少很多代码,因为Lombok会帮忙自动生成很多代码。但是,这些代码是要在编译阶段才会生成的,所以在开发的过程中,其实很多代码其实是缺失的。这就给代码调试带来一定的问题,我们想要知道某个类中的某个属性的getter方法都被哪些类引用的话,就没那么简单了。
  • 影响版本升级
    • Lombok对于代码有很强的侵入性,就可能带来一个比较大的问题,那就是会影响我们对JDK的升级。按照如今JDK的升级频率,每半年都会推出一个新的版本,但是Lombok作为一个第三方工具,并且是由开源团队维护的,那么他的迭代速度是无法保证的。所以,如果我们需要升级到某个新版本的JDK的时候,若其中的特性在Lombok中不支持的话就会受到影响。还有一个可能带来的问题,就是Lombok自身的升级也会受到限制。因为一个应用可能依赖了多个jar包,而每个jar包可能又要依赖不同版本的Lombok,这就导致在应用中需要做版本仲裁,而我们知道,jar包版本仲裁是没那么容易的,而且发生问题的概率也很高。
  • 可能会破坏封装性
    • 一般构建一个类并不会直接生成所有字段的set和get方法,如果使用了lombok中的注解类似于@Data,就会自动将所有适合的字段都生成对应的set和get,就可能会破坏封装性。
  • Lombok虽好,但缺点也不少,如果你在公司团队开发中被强X了,你就只能使用,如果新项目开发,能不用就尽量别用了,否则坑也不少的!
  • 15
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值