第16篇:禁止使用Lombok

📌 系列导航《Java 100 天进阶之路》完整目录 |
⬅️ 上一篇:第15篇:Java控制流程语句 |
➡️ 下一篇:第17篇:Java常用包装类与自动装箱拆箱深入

一、核心知识点

  • Lombok是什么:通过注解自动生成getter/setter、构造方法、equals/hashCode等
  • 常见注解:@Data@Getter@Setter@ToString@EqualsAndHashCode@NoArgsConstructor@AllArgsConstructor@Builder
  • Lombok的优点:减少样板代码,提高开发效率
  • Lombok的缺点与隐患:
    • @EqualsAndHashCode默认不包括父类,导致继承时逻辑错误
    • @ToString可能导致循环引用栈溢出
    • 需要IDE插件,团队协作环境需统一配置
    • 反射、序列化、对象拷贝可能出问题
    • 代码可读性下降,隐藏了实现
  • 企业开发规范:部分大厂禁止或限制使用
  • 替代方案:IDE生成代码、Java 16+record类、手动编写

二、通俗讲解(1分钟开心学)

Lombok是一个Java库,通过在类上加注解,编译时自动生成getter、setter、构造方法、equals、hashCode等。比如你在类上加@Data,就相当于帮你写了十几行代码。

为什么很多人爱用?
因为Java Bean的样板代码太烦了,每个字段都要写getter/setter。

为什么有些公司禁止?

  1. 继承陷阱@EqualsAndHashCode默认callSuper=false,不会比较父类的字段,导致子类的equals逻辑错误。
  2. 循环引用@ToString在双向关联中可能无限递归,导致栈溢出。
  3. 环境要求:IDE需要安装插件,否则代码看起来像缺胳膊少腿;CI构建需要配置注解处理器。
  4. 调试困难:断点看不到自动生成的代码逻辑,反编译后阅读体验差。
  5. 序列化问题:某些序列化框架要求默认构造器,Lombok生成的可能有兼容性问题。
  6. 升级风险:新JDK版本发布后,Lombok可能来不及适配,导致编译失败(如JDK 16的record与Lombok冲突)。

替代方案

  • IDE自带生成功能(IntelliJ中Alt+Insert生成getter/setter/构造器等)。
  • Java 16引入的record类(不可变数据载体),自动生成构造器、equals、hashCode、toString。
  • 手动编写(清晰、可读、可控)。

三、实操代码案例 + 场景说明

场景:在继承体系中,Lombok的@EqualsAndHashCode可能引发bug。

1. 错误示例(Lombok)

import lombok.Data;
import lombok.EqualsAndHashCode;

@Data
class Parent {
    private int id;
}

@Data
// 默认 callSuper = false,不会比较Parent的id
class Child extends Parent {
    private String name;
}

public class Test {
    public static void main(String[] args) {
        Child c1 = new Child(); c1.setId(1); c1.setName("test");
        Child c2 = new Child(); c2.setId(2); c2.setName("test");
        System.out.println(c1.equals(c2));  // true(错误!id不同应该false)
    }
}

2. 修复方式(不使用Lombok或正确配置)

import lombok.EqualsAndHashCode;

@EqualsAndHashCode(callSuper = true)  // 明确包含父类
class ChildCorrect extends Parent {
    private String name;
}

3. 不使用Lombok的手动实现

class Parent {
    private int id;
    // getter/setter...
}

class Child extends Parent {
    private String name;
    
    @Override
    public boolean equals(Object o) {
        if (!super.equals(o)) return false;
        Child child = (Child) o;
        return Objects.equals(name, child.name);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(super.hashCode(), name);
    }
}

4. Java record 替代(最佳实践)

record Person(String name, int age) { }  // 自动生成构造器、equals、hashCode、toString
// 不可变,且没有继承缺陷问题

四、避坑要点

错误/误区 后果 正确做法
继承时使用@Data而不设置callSuper equals/hashCode行为错误 使用@EqualsAndHashCode(callSuper=true)
双向关联中直接使用@ToString StackOverflowError 使用@ToString.Exclude排除循环引用字段
依赖Lombok生成无参构造但字段有final 编译错误 使用@NoArgsConstructor(force = true)或手动处理
项目升级JDK后Lombok未适配 编译失败 先确认Lombok版本支持新JDK,或暂停使用

五、面试高频考点

Q1:Lombok的优点和缺点?

优点:减少样板代码,提高开发效率。缺点:IDE插件依赖、继承场景下的equals/hashCode陷阱、调试困难、版本兼容风险。

Q2:为什么@EqualsAndHashCode默认callSuper=false

为了兼容没有继承的普通类,避免无意义的性能开销。但在继承场景中,这是设计缺陷,需要显式设置callSuper=true

Q3:如果不使用Lombok,如何减少样板代码?

  1. IDE代码生成;2. Java 16+的record;3. 使用Kotlin等替代语言;4. 手动编写+模板。

六、练习题

  1. 代码改错:写出一个继承场景,使用Lombok导致equals错误,并给出正确写法。
  2. 设计:为什么不推荐在大型团队项目中随意使用Lombok?
  3. 实践:将一个简单的POJO类(如User {id, name, email})用record重写,对比代码量。

📊 你的学习进度

  • 当前:第16篇 / 共44篇 · 第二阶段:核心语法与面向对象(第5~20篇)
  • ✅ 已完成:第1~15篇
  • 📖 正在学:第16篇
  • ⏳ 待学习:第17~44篇

👉 📚 完整目录 & 学习指南 | 🔥 订阅本专栏,不错过每一篇

💡 本专栏每篇都包含:避坑表 + 面试高频考点 + 练习题。每天30分钟,100天拿offer!


👉 下一篇预告

《Java常用包装类与自动装箱拆箱深入》

内容简介:8种包装类的详细用法,缓存池原理(IntegerCache),自动装箱拆箱的性能陷阱。

💡 学完这篇,你将彻底掌握包装类,面试再问“128==128”轻松回答。

📌 《Java 100 天进阶之路 | 从入门到上岗就业》 每天一篇,建议收藏 + 关注,一起100天拿offer!
👉 点击关注我,更新后第一时间收到推送!

更多推荐