这是indexloc提供的服务,不要输入任何密码
Skip to content

Change lombok's property capitalization code. Field xName -> getxName(). #2693

@rzwitserloot

Description

@rzwitserloot

This is a catch-all issue that tries to capture the relevant information from a ton of separate issue requests (to those reviewing bug reports, please mark as duplicate of just this issue).

The problem:

Lombok's name conversion tool, used by @Getter and @Setter, as well as @With, and therefore also @Data and @Value, turns a field that starts with a single lowercase letter followed by a capital into a capital followed by a capital: @Getter private String uName; generated public String getUName() {return this.uName; }.

However, various tools out there expect getuName instead, in this unique case where the second letter of the field/property name is a capital where the first is lowercase.

Unfortunately, there is no convention we can follow, because there are also tools out there that expected getUName. No matter what lombok does, some tooling / expectations will be left out in the cold. More generally then, because of these conflicts, names like uName are problematic in any case, and you should try never to use such names.

There is nothing lombok can do to solve all problems with single-lower-case-letter property names: If you decide to use fields named like this, sooner or later you're going to run into trouble. Quoting user @Maaartinus:

Javabeans is fubared. Some long time ago I was unhappy about Lombok mistreating my "uShaped" property and wrote manual etters as a workaround. IIRC it didn't work either, because some other tool didn't understand it in the opposite direction (setuShaped -> uShaped), so I ended using "shapedAsU" instead. 🙄

However, the majority of the community has standardized on xName -> getxName(), and thus we are now willing to accept a PR, even though this will cause no small amount of pain, as it'll be backwards incompatible, and we reserve the right to wimp out and delay integrating the Pull Request until a major update with more breaking changes.

Tools and specs that prefer xName -> getxName:

[context: This describes how to derive a property name from the existence of getX and/or setX methods; it goes from getter to property name, which is the reverse of what lombok does]: ... when we extract a property or event name from the middle of an existing Java name, we normally convert the first character to lower case. However, to support the occasional use of all upper-case names, we check if the first two characters of the name are both upper case and if so leave it alone. So for example, FooBahfooBah, Zz, URLURL.

(warning from @rzwitserloot: Do not write setURL. All major style guides and modern JDK standards say you should write setUrl. This nuance wasn't around in 1997 / it was, but this document tries to cater to existing code that did not follow it; a bunch of JDK methods, particularly in swing, fail to adhere to this, for example).

(It's subtle, but this URLURL rule means that getXName() is turned into property name XName because it starts with 2 capitals. This is presumably the source of why xName -> getxName, because getXName doesn't convert back to xName according to beanspec §8.8.

  • JSP
  • IntelliJ's code generation ('generate getter / setter')
  • Eclipse's code generation ('generate getter / setter')
  • java.beans.Introspector's decapitalize method.

Tools and specs that prefer xName -> getXName:

Tools that used to xName -> getXName but now xName -> getxName:

See also this Stack overflow answer that goes into a lot of depth on this sad state of affairs, as well as this conversation on the lombok list.

Workaround:

Just write the getter/setter out, with the casing you want. Lombok will see it and recognize that you clearly wanted this alternate casing:

@Getter private String xName;

// write out the getter explicitly:
public String getxName() { ... }
// .. and lombok will not generate getXName.

This issue is a catch-all for at least 25 earlier issues; all relevant information from all issues marked as duplicate is included in this one post.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions