实体类使用lombok注解加快开发
前言
Github:https://github.com/HealerJean
一、安装
lombok
是一个可以帮助我们简化java
代码编写的工具类,尤其是简化javabean
的编写。
优点: 即通过采用注解的方式,消除代码中的构造方法,getter/setter等代码,使我们写的类更加简洁,
缺点: 当然,这带来的副作用就是不易阅读…不过,还是能看得懂吧,废话不多说,先看一下 lombok
支持的一些常见的注解。
1、插件 lombok

2、依赖导入
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
二、注解
1、@Data
注解在类上;
@Data
等价@Setter
、@Getter
、@RequiredArgsConstructor
、@ToString
、@EqualsAndHashCode
提供类所有属性的
getting
和setting
方法,此外还提供了equals
、canEqual
、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
注解再字段、类上
用于生成
get
和set
方法,默认是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 isrecommended 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 {
2)问题解决
a、原因
原因;当我们给一个继承了父类的子类上使用 @Data
` @ToString ||
@EqualsAndHashCode注解时,
IDE` 会警告
b、解决方案
在子类上声明
@EqualsAndHashCode(callSuper = true)
@EqualsAndHashCode
是Lombok
提供的一个非常有用的注解,可以自动生成equals
和hashCode
方法,用于生成equals(Object other)
方法和hashCode()
方法的实现。这两个方法通常用于判断两个对象是否相等,以及在哈希表中(如HashSet
、HashMap
等)正确地存储和检索对象。
callSuper = true
:这个属性指定了在生成equals()
和hashCode()
方法时,应该调用父类的相应方法。默认情况下,callSuper
是false
,这意味着生成的equals()
和hashCode()
方法只会比较当前类声明的字段。如果你的类继承自另一个类,并且你希望equals()
和hashCode()
方法的行为能够考虑父类的状态(即父类声明的字段),那么你就应该将callSuper
设置为true
。
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@Data
public class RouteRuleDataV0Dto extends RouteRuleDataBaseDTO implements Serializable {