文章目录
- 介绍
- Lombok原理
- 常用注解
- @Data
- @Getter
- @Setter
- @ToString
- @EqualsAndHashCode
- @NoArgsConstructor
- @AllArgsConstructor
- @RequiredArgsConstructor
- @Accessors(chain = true)
- @Cleanup
- @Builder
- 遇到的问题
- 谨慎使用@Data
-
- @Builder和@Data不能共用
-
介绍
官网:https://projectlombok.org/
Lombok项目是一个java库,它可以自动插入到编辑器和构建工具中,增强java的性能。不需要再写getter、setter或equals方法,只要有一个注解,你的类就有一个功能齐全的构建器、自动记录变量等等。
可以精简我们的代码的,让开发人员把精力放在业务上。
Lombok原理
Java的编译分为以下⼏个阶段:
解析与填充符号表->注解处理->分析与字节码⽣成->⽣成⼆进制class⽂件。
Lombok 使⽤的是 JDK 6 实现的 JSR 269: Pluggable Annotation Processing API (编译期的注解处理器),它是在编译期时把 Lombok 的注解代码,转换为常规的 Java ⽅法⽽实现注⼊。
在编译期阶段,当 Java 源码被抽象成语法树 (AST) 之后,Lombok 会根据⾃⼰的注解处理器动态的修改AST,增加新的代码 (节点),在这⼀切执⾏之后,再通过分析⽣成了最终的字节码 (.class) ⽂件,这就是Lombok 的执⾏原理
常用注解
@Data
为我们的实体类自动生成get、set、hashcode、equals 、toString方法 与不带参数的构造方法。
它是一个混合注释,它包含了@Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode的功能。
@Getter
生成get方法
@Setter
生成set方法
@ToString
生成toString方法
@EqualsAndHashCode
生成equals和hashCode方法
@NoArgsConstructor
生成无参构造
@AllArgsConstructor
生成有参构造
@RequiredArgsConstructor
生成有参构造,对于标有@NonNull注解的字段,还将生成一个显式的null检查
@Accessors(chain = true)
指定set方法通过this返回自己本身,以便于进行级联操作的执行。
@Cleanup
放在本地变量的声明前,自动产生close相关操作,例如IO流
@Builder
生成builder相关操作,方便通过builder的方式创建对象
遇到的问题
总结日常开发使用过程中遇到的问题
谨慎使用@Data
问题
子类不能完全代表父类
@EqualsAndHashCode
注解里有个字段callSuper,它的默认值是false,意思是在重写时,不会将父类的字段写到equals里;而@Data这个注解由于包含了@EqualsAndHashCode
,所以它也有这个特性,即子类强制实现了重写equals和hashCode,并且只重写了自己的属性,这时,问题就来了,当两个对象比较时,如果子类属性相同而父类属性不同,结果也为true,这是非常严重的bug。
总结
在使用@Data时,我们尽量把 @EqualsAndHashCode(callSuper = true)加上,因为你不加,它相当于是false;或者杜绝使用@Data,而用@Getter,@Setter,@ToString代替它。
具体还要取决于您的类层次结构,需要根据具体情况进行检查。
@Builder和@Data不能共用
由于添加@Builder
会将@Data
让类缺失无参构造器,因为很多框架都会调⽤⽆参构造去创建对象,所以会报错。
举例,使用Mybatis plus + Lombok查询数据时,会报下面的错误:
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
Error querying database. Cause: java.lang.IndexOutOfBoundsException: Index 8 out of bounds for length 8
…
Caused by: java.lang.IndexOutOfBoundsException: Index 8 out of bounds for length 8
java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
java.base/java.util.Objects.checkIndex(Objects.java:372)
java.base/java.util.ArrayList.get(ArrayList.java:458)
org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createUsingConstructor(DefaultResultSetHandler.java:709)
org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createByConstructorSignature(DefaultResultSetHandler.java:694)
org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createResultObject(DefaultResultSetHandler.java:658)
org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createResultObject(DefaultResultSetHandler.java:631)
org.apache.ibatis.executor.resultset.DefaultResultSetHandler.getRowValue(DefaultResultSetHandler.java:398)
org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValuesForSimpleResultMap(DefaultResultSetHandler.java:355)
org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValues(DefaultResultSetHandler.java:329)
org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSet(DefaultResultSetHandler.java:302)
org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSets(DefaultResultSetHandler.java:195)
org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:65)
org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:79)
com.baomidou.mybatisplus.core.executor.MybatisSimpleExecutor.doQuery(MybatisSimpleExecutor.java:67)
org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:325)
org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156)
com.baomidou.mybatisplus.core.executor.MybatisCachingExecutor.query(MybatisCachingExecutor.java:163)
com.github.pagehelper.PageInterceptor.intercept(PageInterceptor.java:111)
org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:62)
com.sun.proxy.$Proxy425.query(Unknown Source)
org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:151)
解决
方法一,
在无参构造函数上加上@Tolerate
即可解决,目的是让Lombok在⽣成类的时候,对指定的构造函数不感知。
方法二,
直接使用无参构造器+有参构造器的方式,类上添加注解@RequiredArgsConstructor
来构建有参,添加注解@NoArgsConstructor
来构建无参构造器,即可解决。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)