In Lombok, what is the difference between #AllArgsConstructor and #RequiredArgsConstructor? - java

Lombok offers a variety of annotations for java constructors, including but not limited to #AllArgsConstructor and #RequiredArgsConstructor. What is the difference between these two and when do you use one over the other? I found this documentation but the verbiage is a little convoluted and I'm having trouble following the basic differences between the two.

In short, use #AllArgsConstructor to generate a constructor for all of your class's fields and use #RequiredArgsConstructor to generate a constructor for all class's fields that are marked as final.
From the documentation,
#AllArgsConstructor generates a constructor with 1 parameter for each field in your class.
#RequiredArgsConstructor generates a constructor with 1 parameter for each field that requires special handling. All non-initialized final fields get a parameter, as well as any fields that are marked as #NonNull that aren't initialized where they are declared.

Related

Are static variables included in lombok AllArgsConstructor annotation?

The title pretty much sums it up. I'm wondering if I need to include static variables (which I probably don't) in the constructor.
Given that static variables are static I suspect that they are probably not. But I didnt find any answers to this question on stackoverflow.
No static fields are skipped while using these lombok annotations
#NoArgsConstructor
#RequiredArgsConstructor
#AllArgsConstructor
Static fields are skipped by these annotations.
If you want to declare constructor with static fields then you can declare the one explicitly, but you might end up with compiler error if any of those constructors have same signature
Unlike most other lombok annotations, the existence of an explicit constructor does not stop these annotations from generating their own constructor. This means you can write your own specialized constructor, and let lombok generate the boilerplate ones as well. If a conflict arises (one of your constructors ends up with the same signature as one that lombok generates), a compiler error will occur.
The answer is no as you can check in javadoc:
An all-args constructor requires one argument for every field in the class.
or official documentation: https://projectlombok.org/features/Constructor
RequiredArgsConstructor includes in the constructor all final fields. However, you cannot have a static final variable not initialized (as they can be used even with no instance of that class)

Inheritance with lombok annotation get errors

In my project, lombok is used to avoid writing getters and setters for a class.
I have two classes Child extends Parent:
#Value
#Builder
#AllArgsConstructor
#JsonIgnoreProperties(ignoreUnknown = true)
public class Parent {
#Nonnull
#JsonProperty("personId")
private final String personId;
#JsonProperty("personTag")
private final String personTag;
...
}
And
#Value
#Builder
#AllArgsConstructor
#JsonIgnoreProperties(ignoreUnknown = true)
public class Child extends Parent {
#Nonnull
#JsonProperty("childId")
private final String childId;
...
}
But this doesn't seems work as no default constructor available in Parent. I'm not familiar with the lombok annotation. Is there any good way to extend the Base class and use the lombok annotation at the same time?
TL;DR: add #NonFinal annotation to your superclass
Details: #Value annotation makes the class final, so you cannot inherit from it. Experimental #NonFinal annotation should prevent this.
import lombok.Value;
import lombok.experimental.NonFinal;
#Value
#NonFinal
public class Parent {
REF: https://projectlombok.org/features/Value
NOTE: For performance reasons (if it matters) final (value) objects can be (theoretically) super fast. The optimizer can allocate them in the stack memory, or reuse the same stack block in cycles, so no GC overheads.
(This is similar to how .NET structure value objects are usually allocated by .NET framework)
By adding #NonFinal such an optimization opportunity disappears.
Class hierarchies + lombok doesn't work particularly well, in the sense that the lombok operations done on your Child class don't know anything about parent.
However, your specific question seems answerable:
The Parent class has a constructor that takes all fields, because you asked lombok to make this constructor via #AllArgsConstructor. Therefore, it does not have a no-args constructor. If you want both constructors (the one that takes all fields + a second one that takes no arguments, a.k.a. the default constructor), also add a #NoArgsConstructor annotation to tell lombok that you want that.
NB: #Builder does not work with hierarchy either, but the fresh new #SuperBuilder feature does. I'm pretty sure you want to replace #Builder with #SuperBuilder here. SuperBuilder requires that ALL classes in the hierarchy are annotated with #SuperBuilder and not #Builder.

Add rules when creating a POJO

I'm using lombok's annotation #Data when writing pojos because it automatically generates constructor, hashCode as well as other methods for me. It worked like a charm until I was trying to use #Data in such a pojo class.
#Data
public class MyPojo {
private final String name;
private final int from;
private final int to;
// other fields
}
What I need to do is to restrict values of from and to when creating this pojo so that to will always be greater than from, but it seems that in order to achieve this logic, I have to rewrite the constructor all by myself with lots of code similar to this.name = name.
PS: I think using super from inheritance could be a workaround, but it may make the program harder to be understood.
Is there any better way to satisfy this need?
#Data annotation is not providing any way to validate construction arguments. I feel you need to annotate your pojo with #Getter #Setter #ToString #EqualsAndHashCode annotations and write constructor on your own.
Looking at Lombok's website, I don't see any way to restrict constructor parameters to specific values, especially relative to another variable that may have not been initialized yet. You'll probably have to create a concrete constructor for this class.
but it may make the program harder to be understood
I really wouldn't worry about that as you're already using Lombok, which would make any big program very confusing when trying to track down a specific field/method.

What is the precedence of Lombok annotations?

I know that #EqualsAndHashCode have a precedence over #Data, but what about other annotations? Is there any simple rule that can be used to determine it?
I know just one rule: A more specific annotation takes precedence. As #Data doesn't allow to configure anything about the #EqualsAndHashCode computation details, the latter is clearly more specific. Similarly for #Data vs. #Getter and others.
Another case is class-level vs. field-level annotation, where the former can be overridden by the latter.
Note that doing it the other way round would make no sense at all.
There are some border cases like #Builder vs. #Data, where it's unclear what constructor should be generated (IIRC they require AllArgsConstructor and NoArgsContructor, respectively). Specifying the constructors explicitly helps.

Lombok #Getter and copies of Collections

Using #Getter on a List field works fine, but on attempting to upgrade to Java 8 I encounter ConcurrentModificationExceptions because the getter generated by Lombok does not perform a copy of the field, which is essential should you wish to prevent external modification of the instance's state.
Any ideas how I can get Lombok to copy the Collection on getters, or am I restricted to writing my own?
From #Getter and #Setter documentation:
You can annotate any field with #Getter and/or #Setter, to let lombok generate the default getter/setter automatically.
A default getter simply returns the field, and is named getFoo if the field is called foo (or isFoo if the field's type is boolean). A default setter is named setFoo if the field is called foo, returns void, and takes 1 parameter of the same type as the field. It simply sets the field to this value.
Since you want more functionality then the default getter you'll have to write your own.

Categories