Lombok getter/setter vs Java 14 record - java

I love project Lombok but in these days I'm reading and trying some of the new features of java 14.
Inside the new capability, there is the record keyword that allows creating a class with already built-in the following functionality: constructor, private final fields, accessors, equals/hashCode, getters, toString methods.
Now my question is: is better to rely on the feature of Lombok or should we start using the record functionality:
Is better to use this:
record Person (String name, String surname) {}
or that:
#AllArgsConstructor
#ToString
#EqualsAndHashCode
public class Person {
#Getter private int name;
#Getter private int surname;
}
What are the pros and cons of the both approach?

Lombok, and the record feature of the Java language, are different tools for different things. There is some superficial overlap, but don't let that distract you.
Lombok is largely about syntactic convenience; it is a macro-processor pre-loaded with some known useful patterns of code. It doesn't confer any semantics; it just automates the patterns, according to some knobs you set in the code with annotations. Lombok is purely about the convenience of implementing data-carrying classes.
Records are a semantic feature; they are nominal tuples. By making a semantic declaration that Point is a tuple of (int x, int y), the compiler can derive its representation, as well as construction, declaration, equality, hashing, and string representation protocols, from this state description. Because they carry semantics, readers and frameworks can also reason with higher confidence about the API of records. (This may also be syntactically convenient; if so, that's great.)

NB: Instead of that christmas tree of annotations, you can just use #Value on the class. Note that this makes the class final, and makes all fields both private and final, and gives you all the rest as well. This is close to what records are (they too are final, and all fields inside are final).
record is still in preview, so for production code, obviously it's not, yet, suitable. Use lombok.
Once records are out of preview, it's more complicated. Lombok is FAR more flexible; you can easily swap in some new aspect without having to rewrite all the code (you can just, for example, add an 'extends' clause to your class without having to then handwrite the equals and hashCode method; something records cannot give you). Lombok also gives you more features: You can for example add a builder by adding the #Builder annotation; not something records can do.
If it's highly unlikely you're going to use any of that for the class you're designing - I'd use records.
DISCLAIMER: I'm a core contributor to Project Lombok.

I've been playing around with this combination for some time as well and with the slight bit of hands-on I could list down the following differences:
Lombok
Records are not yet as powerful a tool to eliminate Lombok all together. Note that the library has much more to offer than just the #Getter, #AllArgsConstructor, #ToString, #EqualsAndHashCode.
Experienced by self, the EqualsAndHashCode is not the same as you would expect when it comes to migrating to records.
Records
Records are an official part of the language, with support of all major IDEs
On a different note, if the requirement of your object representation is to be a "data carrier" you can still seek advantage of Records, without relying on an additional library to reduce the boilerplate code to perform that precisely. That is the reason that as a conclusive note this blog reads the following:
It will also help teams eliminate many hand-coded implementations of
the underlying pattern and reduce or remove the need for libraries
like Lombok.
Of course, on a day-to-day basis, it is always wise based on the requirements of a project to choose which way to follow and practice.

While Brian explains well the different goals of Lombok and records, he does not explain when to use which.
If your class is a "transparent, shallowly immutable data aggregate" then a record will do a great job because:
it has even less ceremony than a class annotated with Lombok
it carries the semantic information "this is an immutable data class" (as emphasized in Brian Goetz's answer). This semantic information may be valuable both to programmers and to frameworks.
I would still use Lombok if your class cannot live with the restrictions of records (e.g. immutability, no builder, not extensible).

Java Records don't require any additional dependency, so it's better to use them instead of Lombok I think.
If your project supports Java 14 you can already use them in Eclipse.
There's a plugin in the marketplace for it:
https://marketplace.eclipse.org/content/java-14-support-eclipse-2020-03-415

In short, if you are doing functional coding with Java, use records. Otherwise use Lombok, it is much more flexible and powerful.
There are some exceptions to this rule for e.g. in API coding.

Related

Java getter/setter naming convention when also using records [duplicate]

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?
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:
Records are not the place to look for getters/setters syntactical sugar, as they are not meant to replace JavaBeans.
I strongly agree with you that JavaBeans are too verbose. Maybe an additional feature (called beans instead of records) could be implemented - very similar behavior with the records feature but that would permit mutability. In that case, records and beans would not be mutually exclusive.
As it has been mentioned, records are in preview mode. Let's see what the feedback from community would be.
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...
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"
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.
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.

What is the advantage of annotating an immutable Java class with #Immutable?

I get the concept of immutability, and why it is a good idea to make DTOs immutable.
I also notice that Java has an #Immutable annotation that we can use to annotate immutable classes.
My question is: what does annotating a Java class as #Immutable give us? Are there any library features that only work on classes annotated in this way?
The annotation documents the fact that your class is immutable and tells the users of the class that you have followed the contract defined in the annotation javadoc. It is also frequent to simply include a comment directly in the javadoc: this is the approach chosen by the JDK, see for example the javadoc of LocalDate.
Some static analysis tools such as FindBugs can also use that annotation and verify that the class really is immutable. If you forgot to make a public field final for example, FindBugs will emit a warning.
The main benefit is documentation. The JCIP annotations were introduced without implementations, on the theory that they offered documentation benefits from being written even if they were not checked.
I do not know of any current library feature that depends on your class being annotated as #Immutable.
There are two ways that existence of an #Immutable annotation could potentially affect your program.
At compile time, your program could fail to compile because it did not respect the library's contract -- in other words, the compiler issues a warning if your program contains an immutability bug. This is how the Checker Framework's IGJ Immutability Checker works. Alternately, you could run an additional analysis at build time and fail the build if the analysis fails. This is how FindBugs works (also see MutabilityDetector4FindBugs, a third-party add-on).
At run time, the library could use reflection or a similar analysis to read your program's classfiles. The library could behave differently (such as throwing an error) depending on whether it finds #Immutable annotations.
A caution: there are multiple, equally valid definitions of #Immutable, and it's easy to mix them up which leads to confusion. For instance, is the immutability with respect to the Java heap (no changes whatsoever are permitted to any field), or with respect to the abstract value (internal representation changes are permitted so long as no client can observe them)? As another example, is the immutability shallow (no changes to this object, but changes are permitted to objects it references) or transitive (no changes to this object or to any object that it references)? Does the immutability prevent changes through the given reference or variable, or does it also prevent changes through aliases? Be sure that you understand what choices your tool has made.
what does annotating a Java class as #Immutable give us?
Annotation in Java does not do anything itself, but they are used by external tools. Take a look at very good inspections for such annotations in IntelliJ IDEA.

Why java annotations?

i want to ask why are the java annotations used so much... I know that they replaced xml configuration in for example jpa, but why is this kind configuration used at all?
Consider this piece of code:
#Entity
class Ent{
// some fields
}
//... somewhere in the other file far far away
class NonEnt{
// whatever here
}
Now, when I try to put this in persistence context, with EntityManager's persist method, I get runtime error(better would be to get compile error) with trying to persist NonEnt instance. There is obvious solution for me, force the entities to implement some no-method interface instead of using #Annotations. But this isn't popular among framework designer, what is the drawback of this solution?
Thanks for answering...
When compared to marker interfaces, annotations have some advantages:
they can be parameterized
they are more fine grained - you can attach them not only to classes but also to other class elements (fields, methods, method arguments, etc)
Annotations are also supposedly less intrusive, but this point is matter of taste and debatable.
See also:
Annotations (official JDK documentation)
What is the use of marker interfaces in Java?
The use of annotations is a lot less invasive than forcing the client to implement a interface or extend a class.
There is obvious solution for me,
What you describe is called a "marker interface" and it's an abuse of the interface concept. I suspect the only reason why you consider it obvious is because of Serializable - which only exists because there were no annotations at that time.
force the entities to implement some
no-method interface instead of using
#Annotations. But this isn't popular
among framework designer, what is the
drawback of this solution?
What are its advantages? Annotations have the huge advantage that they can have parameters, and they are much more fine-grained. Marker interfaces only work at the class level.
Citing the java tutorial:
Annotations provide data about a
program that is not part of the
program itself. They have no direct
effect on the operation of the code
they annotate.
Annotations have a number of uses,
among them:
Information for the compiler — Annotations can be used by the
compiler to detect errors or suppress
warnings.
Compiler-time and deployment-time processing — Software tools can
process annotation information to
generate code, XML files, and so
forth.
Runtime processing — Some annotations are available to be
examined at runtime.
As you can see, annotations are a way of specifying meta-data about your types in java, including interfaces, they are in no way a replacement for them.
Java annotation are really helpful when you want to add some additional information to your class, method or instance variable. There are a lot of libraries which use these annotations heavily. These annotations keep the code simple and readable with the power of making changes to the code at runtime.
For example if you have used lombok library, which creates setter, getter and constructor at compile time and saves you lines of code and time.
When compiler executes the code, lomok searches for all the fields marked with #Setter or #Getter annotation and add setter and getter for that field in the class.
One other example is Junit test runner. How junit differentiates between normal helper method in test class and a test. To differentiate between the two it uses #Test annotation.
This tutorial explains how you can use java annotations to create you own test runner.

Useful Java Annotations

I'm interested in finding out exactly which Java annotations people think are most useful during development. This doesn't necessarily have to limited to the core Java API, you may include annotations you found in third party libraries or annotations you've developed yourself (make sure you include a link to the source).
I'm really interested in common development tasks rather than knowing why the #ManyToOne(optional=false) in JPA is awesome...
Include the annotation and a description of why it's useful for general development.
I doled out a bunch of upvotes for other users, but just to give my two cents the only three annotations I use with any regularity in development are the main annotations used directly by the compiler:
#Override - Great for making it explicit in your code when you're overriding another method. Also has the extra benefit of being flagged as a compilation error if you don't override a method the way you think you are (see this other SO post). This flag informs the compiler that you're intending to override something, so if you don't (e.g. you forget an argument in the method signature), the compiler will catch it.
#Deprecated - Indicate whatever you're marking as something that should not be used from this point forward. The compiler will generate warnings for use of any code elements you've marked as deprecated. In general, deprecation says "this was in here in the past, but it may go away in a future version." Make sure you also use the associated "#deprecated" Javadoc flag in conjunction with this too to tell people what they should use instead.
#SuppressWarnings - Tell the compiler to suppress specific warnings it would otherwise generate. This can be useful for things like when you intentionally want to use deprecated methods, you can block out the deprecation warning. I tend to use it a lot to block out everyone's favorite "Serialization UID" warning on serializable classes (whether or not you should do that is another debate for another time). Just handy for those cases where you know something you're doing is generating a warning, but you're 100% sure it's the proper behavior you want.
Look at the Sun Annotations Guide and check out the section "Annotations Used by the Compiler". These three are given a fairly lengthy discussion.
The Java Concurrency in Practice annotations
Very useful for describing exactly how your code is or isn't thread safe...
I find the he concurrency-related annotations defined by Brian Goetz in his book "Java Concurrency In Practice" to be very useful:
#GuardedBy
#Immutable
#NotThreadSafe
#ThreadSafe
They're particularly useful as FindBugs has patterns that use them.
A jar and documentation is freely available at http://www.javaconcurrencyinpractice.com/
#Override has my vote. It makes it instantly clear what your method is about and makes your code more readable.
#Test
(JUnit 4) It's made writing and understanding test files quite a bit cleaner. Plus, the ability to add the expected attribute has saved a few lines of code here and there.
#Deprecated
Introduced in Java 5.
It helps developers see what's deprecated in IDEs. (Prior to this, most IDEs could still pull a #deprecated out of the javadoc comments for a particular method, but this annotation was a nice way to make it meta-information about the method itself, rather than a comment in documentation.)
It's also used by the compiler to print out warnings when you're using deprecated methods.
Personally I've been looking at the JSR303 Bean Validation and the annotations it provides, I imagine these will become more commonplace, there's only a few implementations of the JSR so far, but they provide annotations such as:
#NotNull private String name;
#NotNull #Size(min = 5, max = 30) private String address;
More info here: http://jcp.org/en/jsr/detail?id=303
these should be useful, you can define them in your projects to better communicate intentions:
#ThreadSafe
#Immutable
#ValueObject
#BagOfFunctions (e.g. java.util.Collections)
etc
Here are some Annotations I use in day to day development
Spring:
#Autowired - used to Auto wire beans
#Rollback - If set to true it will rollback all DB operations done inside the test case
JUnit:
#Test - Tell that a method is a test case
#Ignore - If you want to ignore any of the test cases
#Before - Code that should run before each test case
JPA:
#Entity - To tell that a POJO is a JPA Entity
#Column - Map the property to DB column
#Id - tell that a java property is Primary key
#EmbeddedId - Used for Composite Primary Keys
#Transient - This property should not be persisted
#Version - Used to manage optimistic locking
#NamedQuery - Used to declare Native SQLs
#OneToMany - One to Many relationship
#ManyToOne - Many to one Relationship
I have included only the most essential ones.You can find details about all the JPA annotations from the following links.
http://www.oracle.com/technology/products/ias/toplink/jpa/resources/toplink-jpa-annotations.html
http://www.hiberbook.com/
We started using a compile time tool called lombok (http://projectlombok.org/). You annotate classes, members, etc. and methods are automatically generated at compile time. It's a great productivity boost and saves hundreds of lines of tedious coding.
Do you want a toString() method to be automatically generated? Just annotate your class with #ToString.
Tired of having to define getters and setters for your members? Annotate your class with #Getter and / or #Setter and they're automatically added.
Want to have an SLF4J logger to log stuff? #Slf4j creates a private static final logger for you.
#Data
public class MyBean {
// Getters for x and y, setter for y and constructor with x as arg automatically created!
// toString() and hashCode() methods are there too!
private final int x;
private int y;
}
.
#Slf4j
public class SomeClass {
public void doSomething() {
log.info("I've got log.");
}
}
Setting it up is very easy: just add a provided maven dependency. There's also a tiny Eclipse / IntelliJ plugin.
Check out the full list of features there: http://projectlombok.org/features/index.html
Junit 4 provides very useful annotations. Here's a tutorial illustrating the usage of annotations to define tests.
e.g.
#Test(expected= IndexOutOfBoundsException.class) public void empty() {
new ArrayList<Object>().get(0);
}
As Dan pointed out below, TestNG did this originally.
#Given
allows one JUnit test to build upon the return value of another test. Requires JExample.
#FunctionalInterface
Useful to communicate that a particular interface is meant to be functional. If the single abstract method is removed, it'll throw a compilation error.
I started a weekend project to implement a Programming By Contract framework using method and parameter annotations e.g.
//...
myMethod (#NotNull String a, #NotNullOrEmpty String b){
if ( !validate() ){
//raiseException
}
}
I got stuck at the point of getting param values automatically. Java reflection does not have it. never understood several people's ranting on Java till I came across this limitation.

Java Annotations

What is the purpose of annotations in Java? I have this fuzzy idea of them as somewhere in between a comment and actual code. Do they affect the program at run time?
What are their typical usages?
Are they unique to Java? Is there a C++ equivalent?
Annotations are primarily used by code that is inspecting other code. They are often used for modifying (i.e. decorating or wrapping) existing classes at run-time to change their behavior. Frameworks such as JUnit and Hibernate use annotations to minimize the amount of code you need to write yourself to use the frameworks.
Oracle has a good explanation of the concept and its meaning in Java on their site.
Also, are they unique to Java, is there a C++ equivalent?
No, but VB and C# have attributes which are the same thing.
Their use is quite diverse. One typical Java example, #Override has no effect on the code but it can be used by the compiler to generate a warning (or error) if the decorated method doesn't actually override another method. Similarly, methods can be marked obsolete.
Then there's reflection. When you reflect a type of a class in your code, you can access the attributes and act according to the information found there. I don't know any examples in Java but in .NET this is used by the compiler to generate (de)serialization information for classes, determine the memory layout of structures and declare function imports from legacy libraries (among others). They also control how the IDE form designer works.
/EDIT: Attributes on classes are comparable to tag interfaces (like Serializable in Java). However, the .NET coding guidelines say not to use tag interfaces. Also, they only work on class level, not on method level.
Anders gives a good summary, and here's an example of a JUnit annotation
#Test(expected=IOException.class)
public void flatfileMissing() throws IOException {
readFlatFile("testfiles"+separator+"flatfile_doesnotexist.dat");
}
Here the #Test annotation is telling JUnit that the flatfileMissing method is a test that should be executed and that the expected result is a thrown IOException. Thus, when you run your tests, this method will be called and the test will pass or fail based on whether an IOException is thrown.
Java also has the Annotation Processing Tool (apt) where not only you create annotations, but decide also how do these annotations work on the source code.
Here is an introduction.
To see some cool stuff you can do with Annotations, check out my JavaBean annotations and annotation processor.
They're great for generating code, adding extra validations during your build, and I've also been using them for an error message framework (not yet published -- need to clear with the bosses...).
The first thing a newcomer to annotations will ask about annotations is: "What is an annotation?" It turns out that there is no answer to this question, in the sense that there is no common behavior which is present in all of the various kinds of java annotations. There is, in other words, nothing that binds them together into an abstract conceptual group other than the fact that they all start with an "#" symbol.
For example, there is the #Override annotation, which tells the compiler to check that this member function overrides one in the parent class. There is the #Target annotation, which is used to specify what kinds of objects a user defined annotation (a third type of construct with nothing in common with other kinds of annotation) can be attached to. These have nothing to do with one another except for starting with an # symbol.
Basically, what appears to have happened is that some committee responsible for maintaining the java language definition is gatekeeping the addition of new keywords to the java language, and therefore other developers are doing an end run around that by calling new keywords "annotations". And that's why it is hard to understand, in general what an annotation is: because there is no common feature linking all annotations that could be used to put them in a conceptual group. In other words, annotations as a concept do not exist.
Therefore I would recommend studying the behavior of every different kind of annotation individually, and do not expect understanding one kind of annotation to tell you anything about the others.
Many of the other answers to this question assume the user is asking about user defined annotations specifically, which are one kind of annotation that defines a set of integers or strings or other data, static to the class or method or variable they are attached to, that can be queried at compile time or run time. Sadly, there is no marker that distinguishes this kind of annotation from other kinds like #interface that do different things.
By literal definition an annotation adds notes to an element. Likewise, Java annotations are tags that we insert into source code for providing more information about the code. Java annotations associate information with the annotated program element. Beside Java annotations Java programs have copious amounts of informal documentation that typically is contained within comments in the source code file. But, Java annotations are different from comments they annotate the program elements directly using annotation types to describe the form of the annotations. Java Annotations present the information in a standard and structured way so that it could be used amenably by processing tools.
When do you use Java's #Override annotation and why?
The link refers to a question on when one should use the override annotation(#override)..
This might help understand the concept of annotation better.Check out.
Annotations when it comes to EJB is known as choosing Implicit middle-ware approach over an explicit middle-ware approach , when you use annotation you're customizing what you exactly need from the API
for example you need to call transaction method for a bank transfer :
without using annotation :
the code will be
transfer(Account account1, Account account2, long amount)
{
// 1: Call middleware API to perform a security check
// 2: Call middleware API to start a transaction
// 3: Call middleware API to load rows from the database
// 4: Subtract the balance from one account, add to the other
// 5: Call middleware API to store rows in the database
// 6: Call middleware API to end the transaction
}
while using Annotation your code contains no cumbersome API calls to use the middle-
ware services. The code is clean and focused on business logic
transfer(Account account1, Account account2, long amount)
{
// 1: Subtract the balance from one account, add to the other
}

Categories