Reputation: 12356
Java 14 introduced records feature. Record creates getter with the same name as field, so one would write print(person.name())
for example. But old Java bean convention dictates that one should name this method as getName()
.
Using both styles in the same code base does not look very nice. Migrating everything to records is not possible, as they are too limited to replace all use-cases.
Is there any official or semi-official guidelines how to name getters and setters after Java 14 in new code?
Upvotes: 69
Views: 34058
Reputation: 298
Seeing Java move in the right direction warms my heart a bit.
"Get" is possibly the worst verb to get overly abused in programming. In programming it used to always mean no state change, while in English it can also mean "to become" which is state change. See, even I used it as a state change in the beginning of this paragraph (right before the word "overly").
Kent Beck has got this right as early as 1996 in his "Smalltalk best practice patterns" book:
Provide a method that returns the value of the variable. Give it the same name as the variable.
Upvotes: 0
Reputation: 934
I figured I'd address one tacit assumption: that the style guides we have now actually recommend Bean style getters and setters.
None of the style guides I found actually recommend it. One of them remarks that people are divided on the issue. Thus, if you use the convention foo()
and foo(newValue)
, you would be consistent with readily available style guides.
Google Java Style Guide does show some getField
methods, but the actual guidance doesn't mention them.
Brown borrows from Google, same.
Cornell says:
However, a convention in Java is that a function that yields the value of a field (say title) is the name of the field preceded by "get". People are of two minds on this; not everyone thinks it's a good idea. The name "title" could also be used.
Java Conventions same as Google.
Eydean borrows heavily from Google and Sun, same as Google.
Twitter borrows from Google, same as Google.
And lastly, the Java Beans Spec lays out exactly how you name getters and setters to be compatible with Beans in §8.3.1:
Simple properties By default, we use design patterns to locate properties by looking for methods of the form:
public <PropertyType> get<PropertyName>(); public void set<PropertyName>(<PropertyType> a);
If we discover a matching pair of “get<PropertyName>” and “set<PropertyName>” methods that take and return the same type, then we regard these methods as defining a read-write property whose name will be “<propertyName>”. We will use the “get<PropertyName>” method to get the property value and the “set<PropertyName>” method to set the property value. The pair of methods may be located either in the same class or one may be in a base class and the other may be in a derived class.
And even if you completely disregard this:
§ 8.6 A Java Bean can also explicitly specify which properties, events, and methods it supports by providing a class that implements the BeanInfo interface.
Upvotes: 3
Reputation: 428
I stumbled up this when researching naming conventions for my project. Looking at the "recent" additions to the std lib (e.g. Path, FileSystem, HttpRequest, ...) the only more-or-less "pattern" I could detect was that .prop()
implies direct, unmodified access to the field value, and thus existance of the field with that very type.
Whereas "getXXX" conveys that you cannot/should not assume the existence of a field. This property might be calculated, direct field access or read-only wrapped (e.g. List.copyOf
) or converted.
So my conclusion is: if you want to communicate "structure" or enforce the precence of fields use .prop()
. In all other cases stick to getXXX
as it is more flexible (implementers can be entity classes, records or service classes.
Btw: I am aware that there are big offenders to this logic even in the jdk. e.g. BigDecimal
that's why I focused on more recent additions.
Upvotes: 2
Reputation: 2638
The record
spec is now "final" as of Java 17 and this naming convention discrepancy has unfortunately not been addressed. I stumbled upon it when attempting to leverage Records as shallow holder classes to implement interfaces part of an existing domain model.
Whilst this isn't as neat a solution as I'd like, Records can have methods, so you could add "legacy" getters to your record
, as in the following (contrived but simple) example.
public interface Nameable {
public String getName();
}
public record Person(String name) implements Nameable {
public String getName() {
return name; // or return name();
}
}
At least this allows client code to continue to use that tried and tested (over 20 years old) convention, which - let's face it - is used far more than in pure JavaBeans context.
You could say that the language designers have lived up to their remit of "not declaring war on boilerplate"
Upvotes: 10
Reputation: 756
In Java records, object fields must be private and final. So there is just one kind of getter and one kind of setter possible.
In Java classes, object fields may be private or public. In the latter type of field, one can get or set them simply by adding a period and the field name, e.g.
Employee emp = new Employee(); // Nullary constructor
emp.name = "John Schmidt"; // Setter
. . .
. . .
if (emp.name != "Buddy") // Getter
{
emp.bonus = 100.00;
}
Non-private fields are used a lot in Android apps to save memory and time extracting data. But there's no reason not to use them in Java where it's safe to do so.
Now, if you change away from the usual way in Java classes to something like that used in record types, e.g.
String name = emp.name(); // New getter convention for private field
you have a serious risk of confusion by code readers who might misinterpret this as a non-private object field.
And if you change the record getter to what is used in Java objects, i.e.
obj.getField()
then there is a risk of confusion by coder reviewers and possibly a compiler may treat it as a Java object, depending on execution decision criteria.
In short, it's a different type of object to the normal Java class or enum. Its accessors indicate this new type unambiguously. That's how I see it anyhow. Maybe someone on the Java development committee may be able to enlighten us further.
Upvotes: -3
Reputation: 414
Quote from JEP 359:
It is not a goal to declare "war on boilerplate"; in particular, it is not a goal to address the problems of mutable classes using the JavaBean naming conventions.
My understanding, based on the same document is that records are transparent holders for shallowly immutable data
.
That being said:
All in all, IMHO they are a step forward... I wrote this example set where you can see a code reduction to ~15% LOC from standard JavaBeans.
Also, note that records behave like normal classes: they can be declared top level or nested, they can be generic, they can implement interfaces
(from the same document). You can actually partly simulate JavaBeans (only getters would make sense, though) by extracting an interface containing the getters - however that would be a lot of work and not a really clean solution...
So, based on the logic above, to address your question, no - I didn't see any (semi)official guideline for getters and setters and I don't think that there is a motivation for it right now because, again, records are not a replacement for JavaBeans...
Upvotes: 28