-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Description
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
:
- JavaBeans Specification (last updated: 1997!), §8.8. Quoting from this PDF, as it is often slow or impossible to download:
[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,
FooBah
➝fooBah
,Z
➝z
,URL
➝URL
.
(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 URL
➝ URL
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
'sdecapitalize
method.
Tools and specs that prefer xName
-> getXName
:
- The 'naming a method' conventions as spelled out in oracle's own java tutorial, section 'Defining Methods § Naming a Method'
- IntelliJ's built-in linter (which considers the
getx
ingetxName
to not be a word, following the convention explained in the previous point). Yes, intellij's built in code generator can generate code that is marked as problematic by its built-in linter. - Kotlin (SOURCE: this StackOverflow answer).
- Jackson, which defaults to this behaviour but has a setting to switch to the other behaviour (SOURCE: this issue).
java.beans.PropertyDescriptor
, which uses internal classjava.beans.NameGenerator
'scapitalize
method.- The human visual cortex.
getuName()
is a lot harder to read as 'get the uName property' versusgetUName
.
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.