Lombok 为多个 Field 只生成了一组 getter/setter
起因
项目中使用了 lombok
,发现代码中在调用一个对象的 getter/setter 方法时,IDE 可以正常识别并提示,但是真正编译时是无法通过的,会报错找不到 getter/setter。
环境
- JDK 11.0.8
- lombok 1.18.12
- IDEA 2020.2.1
TestEntity.java
@NoArgsConstructor
@Data
public class TestEntity {
private String testField;
private String testfield;
}
TestEntity.class
public class TestEntity {
private String testField;
private String testfield;
public TestEntity() {
}
public String getTestField() {
return this.testField;
}
public void setTestField(final String testField) {
this.testField = testField;
}
...
}
通过测试可以发现 lombok 为两个 field 只生成了一组 getter/setter,从直觉上可以猜测问题很有可能是出在 field name 上。
分析
通过查阅 lombok documentation ,可以确定确实是 field name 的原因。
No method is generated if any method already exists with the same name (case insensitive) and same parameter count.
如果已经存在具有相同名称(不区分大小写)和相同参数计数的方法,则不会生成任何方法。
Issues 中已经有人提过这个问题,提交 lombok issues 2130 的人认为这是一个不合理的行为,并且建议可以通过为注解增加属性,诸如 @Setter(caseSensitive = true)
的形式来解决这个问题。
其中一个参与讨论的人认为,由于 Javabean 规范并不强制要求 field name 与 getter/setter 要一一对应。并且有人不喜欢 lombok 生成的名称,会使用自己的规则手动定义 getter/setter。因此名称可能会冲突,所以当 lombok 看到具有相同名称的方法时,就不会继续生成同名方法。增加注解属性的方式会提升复杂度以及带来更大数量级的开销,而 lombok 只有少数贡献者和两名主要维护者。也许引入 lombok.config
是最好的选择,但是许多类似的建议都被否决了。因为满足所有人的意愿会导致产生大量的选择,这些选项会以无法预料的方式进行交互,从而导致意外的错误和维护成本。
官方对这个说法表示肯定,知道存在这种情况,但是由于上述原因,以及这种情况并不普遍,所以不会为具有相同的不区分大小写名称的多个字段添加支持。
想法
与之前遇到的情况不同,相比 field name 为 aName
的形式,本例中的 field name 命名尽管只有大小写的区别,可能会带来迷惑,可能被 IDE 提示为 typo,但是单看 testField
和 testfield
的形式还是符合规范的,或者说在调用 Introspector.decapitalize()
时,能够获得预期的结果。所以我也更倾向于认为是 lombok 的策略不合理。
对于 aName
的形式,主流 IDE 为我们显式生成的都是 getaName()/setaName()
,而 lombok 生成的是 getAName()/setAName()
。从实际使用来看,前者在各种工具使用中会更「安全」一点,后者反而会带来异常。
对于这个问题,也有人已经提过了 lombok issues 757 。官方的态度是,由于无论怎么做都会与另一半的内容不兼容,所以不妨坚持目前已经支持的一半,也就是不做修改,并且不考虑增加属性,或是引入新的注解。
突然想起来至少七、八年前就听过一种说法,有人用 「IDE 快捷键为 aName
生成的 getter/setter 是 getaName()/setaName()
」来举例,想说明 IDE 的功能不是足够的可信。事实上,我认为 IDE 做的是正确的事情,同时也是第一次真正理解了为什么有很多人反对在项目中引入 lombok。
最近 IDEA 在升级到 2020.2 的时候,也出现了 lombok 插件存在 bug 的情况,直到 2020.2.1 的时候才修复。也难怪那么多人请愿,希望由 JetBrains 官方来维护 lombok 插件。
回到这个问题本身,修复 bug 也很简单,只要主动为这些只有大小写不同的 fields 显式的编写 getter/setter 即可。
但是…
IDE: 也许应该抛弃 lombok。
JAVA 14: 你知道现在有 record 了吗?
Kotlin: 你们还有这种问题?