前言

Github:https://github.com/HealerJean

博客:http://blog.healerjean.com

一、安装

lombok 是一个可以帮助我们简化 java 代码编写的工具类,尤其是简化 javabean 的编写。

优点: 即通过采用注解的方式,消除代码中的构造方法,getter/setter等代码,使我们写的类更加简洁,

缺点: 当然,这带来的副作用就是不易阅读…不过,还是能看得懂吧,废话不多说,先看一下 lombok 支持的一些常见的注解。 

1、插件 lombokWX20180314-192308

WX20181009-165118@2x

2、依赖导入

<!-- lombok -->
<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
</dependency>

二、注解

1、@Data

注解在类上; @Data 等价@Setter@Getter@RequiredArgsConstructor@ToString@EqualsAndHashCode

提供类所有属性的 gettingsetting 方法,此外还提供了equalscanEqual、hashCode、toString 方法

举例

@Data
public class EntityBean {

    String name;

    public static void main(String[] args) {
        EntityBean entityBean = new EntityBean();
        entityBean.setName("HealerJean");
        System.out.println(entityBean.getName());
    }
}

控制台 HeaelrJean

2、Getter@Setter

注解再字段、类上

用于生成 getset 方法,默认是 public 的,除非向下面一样指定

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

    @Setter(AccessLevel.PROTECTED)
    private int age;

    @Getter(AccessLevel.PUBLIC)
    private String language;

}

等价于
public class GetSeter{
    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;
    }
}

3、@AllArgsConstructor@NoArgsConstructor

@AllArgsConstructor有参构造器

@NoArgsConstructor无参构造器

@AllArgsConstructor(access = AccessLevel.PROTECTED) //指定方法的封装为protect
@NoArgsConstructor
public class ArgsConstructor {
    private int x;

    public static void main(String[] args) {
        //有参构造器
        ArgsConstructor argsConstructor = new ArgsConstructor(2);
    }

}


等价于

public class Shape {
    private int x;
    private String name;

    public Shape(){
    }

    protected Shape(int x,String name){
 			 this.x = x;
        this.name = name;
    }
}

4、@Slf4j

@Slf4j :这个注解用在类上,可以省去从日志工厂生成日志对象这一步

@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);


5、@Accessors

属性chain,用来改变set方法的void变成this.对我而言,在第一次根据别人博客学cas的时候遇到过

@Data
@Accessors(chain = true)
public class SessionKeyResult {

    private String openid;
    private String sessionKey;

    public static void main(String[] args) {
        SessionKeyResult sessionKeyResult = new SessionKeyResult();
        sessionKeyResult.setOpenid("HealerJean").setSessionKey("Jean")
    }
}


6、@builder

1)和 @Data

通常是 @Data@Builder 会一起用在同个类上,既方便我们流式写代码,也方便框架做事,只使用@Builder则不能打印内容

//1、不加@Data
@Builder
public class DemoEntity05Builder {

  private String name;

}

/**
* 不加@Data注解打印数据为null
*/
@Test
public void testBuilder(){
  DemoEntity05Builder demoEntity05Builder = DemoEntity05Builder.builder().name("HealerJean").build();
  log.info(JSONObject.fromObject(demoEntity05Builder).toString());
  //null
}


//2、加上@Data
@Data
@Builder
public class DemoEntity05Builder {
  private String name;
}

/**
* 不加@Data注解打印数据为null
*/     
@Test
public void testBuilder(){
  DemoEntity05Builder demoEntity05Builder = DemoEntity05Builder.builder().name("HealerJean").build();
  log.info(JSONObject.fromObject(demoEntity05Builder).toString());
  //{"name":"HealerJean"}
}


2)和@NoArgsConstructor@AllArgsConstructor

使用构造器的时候,不加@NoArgsConstructor@AllArgsConstructor 会报错,所以两个全部加上

@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class DemoEntity05Builder {
    private String name;

}

@Test
public void testBuilder2(){
  DemoEntity05Builder demoEntity05Builder = new DemoEntity05Builder();
  demoEntity05Builder.setName("healerjean2");
  log.info(JSONObject.fromObject(demoEntity05Builder).toString());
}

7、@ToString

java.lang.Object 中有个实例方法 toString ,这个方法的作用是一个对象的自我描述。在源码中有这样一句注释,It is recommended that all subclasses override this method .即推荐所有的子类重新该方法。

因为该方法在 Object 中的实现是返回字符串——类名和该对象的 hashCode 用“@”符连接起来的字符串,不具有可读性

所以,需要重写该方法,使得该方法能够清楚地表述自己的每一个成员变量。现在,我们在已经创建的 Student 类,重写该方法。

1)不加 @ToString

public class DemoEntity06_ToString {

  private String name;

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


@Test
public void testToString(){
  DemoEntity06_ToString demoEntity05Builder = new DemoEntity06_ToString();
  demoEntity05Builder.setName("healejean");

  System.out.println(demoEntity05Builder);
  //com.hlj.data.bean.demo.DemoEntity06_ToString@2ddc8ecb

  log.info(demoEntity05Builder.toString());
  // com.hlj.data.bean.demo.DemoEntity06_ToString@2ddc8ecb
}

2)加 @ToString

@ToString
public class DemoEntity06_ToString {

  private String name;

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


@Test
public void testToString(){
  DemoEntity06_ToString demoEntity05Builder = new DemoEntity06_ToString();
  demoEntity05Builder.setName("healejean");

  System.out.println(demoEntity05Builder);
  //DemoEntity06_ToString(name=healejean)

  log.info(demoEntity05Builder.toString());
  //DemoEntity06_ToString(name=healejean)
}

8、@SneakyThrows

@SneakyThrows 能在不显式地使用 try-catch 块捕获异常或者在方法签名中声明抛出异常的情况下,抛出受检查异常(Checked Exception)。从而绕过 Java 编译器对受检查异常的检查。实际抛出的还是实际类型的异常

优点:

  • 代码简洁:可以避免在方法签名中列出大量的异常,也无需编写冗长的 try-catch 块,让代码更加简洁易读。
  • 方便开发:在某些情况下,异常处理可能并不是重点,使用 @SneakyThrows 可以让开发者更专注于业务逻辑的实现。

缺点:

  • 隐藏异常信息:由于异常被包装成非受检查异常抛出,调用者可能无法从方法签名中得知该方法会抛出哪些异常,增加了代码的维护难度。
  • 违反 Java 异常处理原则Java 的受检查异常机制旨在强迫开发者处理可能出现的异常,而 @SneakyThrows 绕过了这个机制,可能导致异常处理不规范。

注意事项:

  • 指定异常类型@SneakyThrows 注解可以指定要抛出的异常类型,例如 @SneakyThrows(IOException.class),这样就只会处理指定类型的异常。
  • 谨慎使用:虽然 @SneakyThrows 可以让代码更简洁,但在实际开发中应该谨慎使用,尤其是在公共 API 方法中,建议还是遵循 Java 的异常处理原则,显式地声明和处理异常。

总结:虽然 sneakyThrow 方法最终返回的是 RuntimeException 类型,但实际上抛出的异常类型是传入的 t 的实际类型。通过泛型和类型擦除机制,Lombok 实现了绕过编译器对受检查异常的检查,让代码在编写时更加简洁,但也可能会隐藏异常信息,增加代码的维护难度,所以使用时需要谨慎。

public static RuntimeException sneakyThrow(Throwable t) {
    if (t == null) {
        throw new NullPointerException("t");
    } else {
        return (RuntimeException)sneakyThrow0(t);
    }
}

private static <T extends Throwable> T sneakyThrow0(Throwable t) throws T {
    throw t;
}

三、问题汇总

1、@Accessors 导致 easy excel读取为字段值空

去掉 @Accessors 注解

2、Generating equals

1)问题出现

@Accessors(chain = true)
@Data
public class RouteRuleDataV0Dto extends RouteRuleDataBaseDTO implements Serializable {

image-20220804125354946

2)问题解决

a、原因

原因;当我们给一个继承了父类的子类上使用 @Data   ` @ToString || @EqualsAndHashCode 注解时,IDE` 会警告

b、解决方案

在子类上声明 @EqualsAndHashCode(callSuper = true)

@EqualsAndHashCodeLombok 提供的一个非常有用的注解,可以自动生成 equalshashCode 方法,用于生成 equals(Object other) 方法和 hashCode() 方法的实现。这两个方法通常用于判断两个对象是否相等,以及在哈希表中(如 HashSetHashMap 等)正确地存储和检索对象。

callSuper = true:这个属性指定了在生成 equals() hashCode() 方法时,应该调用父类的相应方法。默认情况下,callSuperfalse,这意味着生成的 equals() hashCode() 方法只会比较当前类声明的字段。如果你的类继承自另一个类,并且你希望 equals() hashCode() 方法的行为能够考虑父类的状态(即父类声明的字段),那么你就应该将 callSuper 设置为 true

@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@Data
public class RouteRuleDataV0Dto extends RouteRuleDataBaseDTO implements Serializable {

ContactAuthor