Java 中之所以充斥着大量冗长的 getter 和 setter,主要源于语言设计哲学 + 历史包袱 + 企业级开发需求的三重叠加,而不是单纯的“Java 故意要写得啰嗦”。
下面从几个核心维度拆解清楚为什么会这样,以及现在(2025–2026 年)实际情况已经发生很大变化。
1. 根本原因:Java 的封装哲学 + 防御性编程传统
Java 从诞生起就强调“封装”(Encapsulation)是面向对象三大基石之一。
- 直接暴露 public 字段被视为严重的设计缺陷(违反信息隐藏原则)
- 字段必须 private → 外部访问必须通过方法 → 于是就诞生了 getter/setter
为什么不直接用 public 字段?
| 场景 | 如果直接 public field | 用 getter/setter 的好处(Java 设计者视角) |
|---|---|---|
| 未来想加校验(非空、范围) | 改成方法后所有调用方都要改代码 | 可以后期在 setter 里加逻辑,不改调用方接口 |
| 想改内部实现(从 int 改 long) | 调用方类型爆炸 | getter 返回类型不变,内部实现随意改 |
| 加日志/监控/缓存/触发事件 | 无法拦截 | setter 里可以加埋点、通知观察者、失效缓存等 |
| 子类想重写访问行为 | 基本不可能 | 可以 override getter/setter |
| 接口/抽象类规范 | 字段不能出现在接口里 | 方法可以出现在接口里(Java 8 前唯一方式) |
一句话:getter/setter 不是为了当前写代码方便,而是为了“未来改动时不炸调用方”。这在 1995–2010 年代的企业级、库开发场景下是极其重要的设计考量。
2. 历史包袱:Java 早期没有 record / data class
- Java 1.0 ~ Java 15:没有任何内置语法糖来消除 boilerplate
- 当时主流 IDE(Eclipse、IntelliJ)都靠自动生成 getter/setter 来缓解痛苦
- 这就形成了“路径依赖”:大家习惯了 → 规范要求写 → 新人继续写 → 恶性循环
对比其他语言:
| 语言 | 原生解决方案 | 出现时间 | Java 对应时间点 |
|---|---|---|---|
| C# | 属性(property) | 2002 年 | Java 21(record + 即将的 property?) |
| Kotlin | data class + var/val | 2011/2016 | Java 14(record 2020) |
| Scala | case class | 2004 | — |
| Java | record(不可变) + Lombok(可变) | record: Java 14 | 终于在 2020 年补上 |
Java 补上 record 已经晚了 20 年,导致前 20 年代码里全是手写/生成出来的 getter/setter。
3. 企业级规范的强化作用
阿里、华为、美团等大厂 Java 开发手册里基本都写着:
- “[强制] 所有的 POJO 类属性必须使用包装数据类型”
- “setter/getter 命名要规范”
- “禁止直接访问字段”
这些规范进一步固化了“必须写 getter/setter”的文化。即使你个人觉得多余,在团队/公司代码审查里也过不了。
4. 2025–2026 年实际情况:已经大幅缓解,但遗留代码还在
现在写新代码已经远没有以前那么痛苦:
| 解决方案 | 现状(2025–2026) | 实际使用率(大厂新项目) | 效果 |
|---|---|---|---|
| Lombok | @Data / @Getter / @Setter / @Builder | 极高(80%+ 项目) | 基本消灭样板代码 |
| Java Record | 不可变数据类,自动生成 equals/hashCode/toString/getter | 中高(新领域模型常用) | 干净很多 |
| IntelliJ 自动生成 | Alt+Insert 一键生成 | 标配 | 至少不手写 |
| Spring Boot + Jackson | 很多场景直接用 record + @JsonProperty | 上升中 | — |
真正还在“充斥冗长 getter/setter”的地方是:
- 10 年以上老项目
- 严格要求“零依赖”的库/模块(不允许用 Lombok)
- 一些对代码可读性/可维护性有极端要求的金融/电信系统(他们宁可多写代码也不加 Lombok)
小结:一句话回答
Java 之所以曾经充斥冗长 getter/setter,是因为早期语言设计为了强封装 + 防御性编程 + 向后兼容,牺牲了表达力,而企业级开发又把这种做法写进了规范。
但现在(2025–2026)新项目已经基本不痛苦了:用 Lombok 或 record 后,代码量和现代语言差距很小。真正还在写一堆 getter/setter 的,要么是老代码,要么是团队规范还没跟上时代。
你现在项目里还在大量手写 getter/setter 吗?还是已经全 Lombok / record 化了?