From: https://mp.weixin.qq.com/s/7HebsMsH21LuDWPbHg6UBw
Lombok is a magical java class library. It can automatically generate annotations to annoy annoying Getter s and Setter s in java beans. It can also automatically generate logger, ToString, HashCode, Builder and other java features or functions that conform to design patterns. It can make your java beans more concise and beautiful.
lombok's idea is very advanced. It allows us to omit tedious template code and do not spend too much time on repetitive code. It is also an inevitable idea in the evolution of Java language. It takes 20% of the time to do 80% of the things.
Now let's look at the specific usage of lombok.
@Data
@ Data is a convenient annotation that is bound to @ToString, @EqualAndHashCode, @Getter/@Setter, and @RequiredArgsConstructor. In other words, @Data generates all boilerplate code associated with simple POJOs (Plain Old Java Objects) and bean s, such as getting all attributes, setting all inheritable attributes, adapting to toString, equals, and hashcode implementations, initializing all final attributes through constructive methods, and all There is no non-final field in the initializer that uses the @NonNull tag to ensure that the field is never null.
@ Data is like implicitly using @toString, @EqualAndHashCode, @Getter, @Setter and @RequiredArgsConstructor annotations on classes. @ Data = @Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor
However, @Data cannot set the parameters of these annotations, such as callSuper, includeFieldNames, and exclude.
If you need to set non-default values for any of these parameters, simply explicitly add these comments;
All generated getters/setters are public by default. To override the access level, annotate fields or classes with explicit @Setter Getter annotations. You can use this annotation (combined with AccessLevel.NONE) to prohibit the use of getter or setter.
All fields marked with transient are not considered hashcode and equals. All static fields will be skipped completely (regardless of any generated methods, and setter / getter will not be created for them).
If the class already contains a method with the same name and parameter count as any commonly generated method, it will not generate the method, nor will it issue warnings or errors.
For example, if you mark a method with equals, it will not regenerate an equals method, even though technically, it may be completely different because of different parameter types. The same rules apply to constructors (any explicit constructor prevents @Data from generating one), as well as toString, equals, and all getter s and setter s.
You can use @ lombok. experiment. Tolerate to tag any constructors or methods to hide them in Lombok
For example:
import lombok.AccessLevel; import lombok.Data; import lombok.Setter; import lombok.ToString; @Data public class DataExample { private final String name; @Setter(AccessLevel.PACKAGE) private int age; private double score; private String[] tags; @ToString(includeFieldNames = true) @Data(staticConstructor = "of") public static class Exercise<T> { private final String name; private final T value; } }
This is equivalent to the following example without lombok:
import java.util.Arrays; public class DataExample { private final String name; private int age; private double score; private String[] tags; public DataExample(String name) { this.name = name; } public String getName() { return this.name; } void setAge(int age) { this.age = age; } public int getAge() { return this.age; } public void setScore(double score) { this.score = score; } public double getScore() { return this.score; } public String[] getTags() { return this.tags; } public void setTags(String[] tags) { this.tags = tags; } @Override public String toString() { return "DataExample(" + this.getName() + ", " + this.getAge() + ", " + this.getScore() + ", " + Arrays.deepToString(this.getTags()) + ")"; } protected boolean canEqual(Object other) { return other instanceof DataExample; } @Override public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof DataExample)) return false; DataExample other = (DataExample) o; if (!other.canEqual((Object)this)) return false; if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false; if (this.getAge() != other.getAge()) return false; if (Double.compare(this.getScore(), other.getScore()) != 0) return false; if (!Arrays.deepEquals(this.getTags(), other.getTags())) return false; return true; } @Override public int hashCode() { final int PRIME = 59; int result = 1; final long temp1 = Double.doubleToLongBits(this.getScore()); result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode()); result = (result*PRIME) + this.getAge(); result = (result*PRIME) + (int)(temp1 ^ (temp1 >>> 32)); result = (result*PRIME) + Arrays.deepHashCode(this.getTags()); return result; } public static class Exercise<T> { private final String name; private final T value; private Exercise(String name, T value) { this.name = name; this.value = value; } public static <T> Exercise<T> of(String name, T value) { return new Exercise<T>(name, value); } public String getName() { return this.name; } public T getValue() { return this.value; } @Override public String toString() { return "Exercise(name=" + this.getName() + ", value=" + this.getValue() + ")"; } protected boolean canEqual(Object other) { return other instanceof Exercise; } @Override public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof Exercise)) return false; Exercise<?> other = (Exercise<?>) o; if (!other.canEqual((Object)this)) return false; if (this.getName() == null ? other.getValue() != null : !this.getName().equals(other.getName())) return false; if (this.getValue() == null ? other.getValue() != null : !this.getValue().equals(other.getValue())) return false; return true; } @Override public int hashCode() { final int PRIME = 59; int result = 1; result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode()); result = (result*PRIME) + (this.getValue() == null ? 43 : this.getValue().hashCode()); return result; } } }
@NonNull
You can use @NonNull to generate null - check for methods or constructors
If Lombok generates the entire method or constructor for you (such as @Data), Lombok always treats annotations on fields commonly referred to as @NonNull as signals to generate null checks. Now, however, using lombok's own @lombok.NonNull on parameters causes only null-check statements to be inserted into your own methods or constructors.
The Null - Check statement looks like the following statement
if(param == null){ throw new NullPointerException("param is marked @NonNull but is null") }
This empty sentence will be judged at the beginning of the method.
public class NonNullExample { @Getter private String name; public NonNullExample(@NonNull String name){ this.name = name; } }
This code with @NonNull null is equivalent to the following code
import lombok.NonNull; public class NonNullExample { private String name; public NonNullExample(@NonNull String name) { if (name == null) { throw new NullPointerException("name is marked @NonNull but is null"); } this.name = name; } }
@Getter & @Setter
You can use @Getter and @Setter to automatically generate any getter/setter.
The default getter returns only the name of the field, getFoo() if the name of the field is foo, and isFoo() if the field type is boolean. If the field is foo, the default setter returns setFoo with a void type and takes a field that is the same as that property as a parameter for assigning values to this property field.
Unless you specify the AccessLevel access level, the method generated using Getter / Setter defaults to the scope of public. AccessLevel has access levels of PUBLIC, PROTECTED, PACKAGE, and PRIVATE.
You can also use @Getter/ @Setter on a class, in which case all non-static attributes in the class are generated with get and set methods.
You can also disable the generation of any get and set methods by setting AccessLevel.NONE. This invalidates the annotations for @Data, @Getter/ @Setter.
public class GetterSetterExample { @Setter @Getter private int age = 10; @Setter(AccessLevel.PROTECTED) private String name; @Getter(AccessLevel.PRIVATE) private String high; }
Equivalent to
public class GetterSetterExample { private int age = 10; private String name; private String high; public int getAge() { return age; } public void setAge(int age) { this.age = age; } protected void setName(String name) { this.name = name; } private String getHigh(){ return high; } }
@ToString
@ ToString annotations are used to replace the implementation of the toString() generation method, which by default prints your class name and each field in sequence, separated by commas.
By setting includeFieldNames = true, the toString() method can print the attribute values and names of each field.
By default, all non-static properties are printed. If you want to exclude certain fields, you need to set @ToString.Exclude, or you can specify ToString (only Explicitly Included = true) to specify which fields you want to use. Then use @ ToString.Include to tag each field to be included.
By setting callSuper to true, the output of the superclass implementation of toString can be included in the output. Note that the toString() implementation of java.lang.Object doesn't make any sense, so you probably won't do this unless you want to extend another class.
You can also include the output of method calls in toString. Only instance (non-static) methods with no parameters can be included. For this purpose, use the @ ToString.Include tagging method.
You can use @ToString.Include (name = some other name) to change the name used to identify members, and you can change the printing order of members by @ ToString.Include (rank = 1). Members without a defined level default to level 0. Members with higher levels are printed first. Members with the same priority are printed in the order in which they appear in the source file.
@ToString public class ToStringExample { //Static attributes will not include private static final int STATIC_VAR = 10; private String name; private String[] tags; private Shape shape = new Square(5, 10); //Excluding specified fields will not be printed by toString @ToString.Exclude private int id; public String getName() { return this.name; } //callSuper denotes whether to extend the parent class toString(), //includeFieldNames denotes whether the attribute name is included @ToString(callSuper = true, includeFieldNames = true) public static class Square extends Shape{ private final int width, height; public Square(int width, int height) { this.width = width; this.height = height; } } public static class Shape {} }
Test the example above
ToStringExample toStringExample = new ToStringExample(); System.out.println(toStringExample);
The output is as follows
ToStringExample(name=null, tags=null, shape=ToStringExample.Square(super=com.project.lombok.ToStringExample$Square@1b9e1916, width=5, height=10))
Remark callSuper = true, and the test results are as follows
ToStringExample(name=null, tags=null, shape=ToStringExample.Square(width=5, height=10))
As you can see from the output, if the parent class is not extended, the inner class information about Shape will not be output, and callSuper defaults to false.
If you comment out includeFieldNames, the test results will not change, so the default value of includeFieldNames is true.
Change includeFieldNames = false, and the test results are as follows
ToStringExample(name=null, tags=null, shape=ToStringExample.Square(super=com.project.lombok.ToStringExample$Square@1b9e1916, 5, 10))
As you can see from the output, if you set includeFieldNames = false, the field name information in Shape will not be output.
The example above with the @ToString annotation is equivalent to the following code
import java.util.Arrays; public class ToStringExample { private static final int STATIC_VAR = 10; private String name; private Shape shape = new Square(5, 10); private String[] tags; private int id; public String getName() { return this.getName(); } public static class Square extends Shape { private final int width, height; public Square(int width, int height) { this.width = width; this.height = height; } @Override public String toString() { return "Square(super=" + super.toString() + ", width=" + this.width + ", height=" + this.height + ")"; } } @Override public String toString() { return "ToStringExample(" + this.getName() + ", " + this.shape + ", " + Arrays.deepToString(this.tags) + ")"; } public static class Shape {} }
@EqualsAndHashCode
Any class definition can be annotated with @EqualsAndHashCode, allowing lombok to generate equals and hashCode methods for it. By default, it will be used on non-static, non-transient ly tagged fields, but you can modify which fields to use by @EqualsAndHashCode.Include or @EqualsAndHashCode.Exclude tag type members.
Alternatively, you can specify exactly the fields or methods you want to use by using @EqualsAndHashCode.Include and using @EqualsAndHashCode (onlyExplicitlyIncluded = true) tags.
If @EqualsAndHashCode is applied to extend another class, this feature becomes dangerous. Generally speaking, automatic generation of equals and hashcode methods for classes is not a good choice because superclasses also define fields that require equals / hashCode methods. By setting callSuper to true, equals and hachcode methods of superclasses can be included in the generated methods.
For hashCode, the result of super.hashCode includes a hash algorithm. For equals, if the superclass implementation considers that it is not equal to the incoming object, the generated method returns false. Note that not all equals implementations handle this situation correctly. However, the equals implementation generated by lombok can handle this situation correctly.
Setting callSuper to true when not extending a class (extending only any java.lang.Object class) prompts compilation errors because lombok converts the generated equals() method and hashCode() implementation into inheritance from Object: only the same Object objects are equal to each other and have the same hashCode.
When you inherit other classes without setting callSuper to true, you are warned, because unless the parent class does not have the same properties, Lombok cannot generate an implementation for you for fields that consider superclass declarations. You need to write your own implementation class or rely on the callSuper tool. You can also configure key using lombok.equals AndHashCode.callSuper.
Here's an example
@EqualsAndHashCode public class EqualsAndHashCodeExample { private transient int transientVar = 10; private String name; private double score; @EqualsAndHashCode.Exclude private Shape shape = new Square(5,10); private String[] tags; @EqualsAndHashCode.Exclude private int id; public String getName() { return name; } @EqualsAndHashCode(callSuper = true) public static class Square extends Shape { private final int width,height; public Square(int width,int height){ this.width = width; this.height = height; } } public static class Shape {} }
@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor
lombok has three annotations for generating constructors. Here's a look at their instructions and examples
@ NoArgsConstructor generates a parametric constructor. If there are final modified fields and no final modified fields are initialized, simple use of the @NoArgsConstructor annotation will prompt compilation errors.
Modification Suggestion: You need to specify an attribute for @NoArgsConstructor @NoArgsConstructor(force=true), lombok will add the initial value by default for the final field above, because id is int type, so the initial value of id is 0, similar to the initial value of different types of fields are false / null / 0, specific Java constructs For example, hibernate and service providers need parametric construction methods. This annotation is mainly used in combination with @Data or other constructors that generate annotations.
Here's one thing to note: Don't use @NonNull with @NoArgs Constructor
@NoArgsConstructor @Getter public class NoArgsConstructorExample { private Long id ; private @NonNull String name; private Integer age; public static void main(String[] args) { System.out.println(new NoArgsConstructorExample().getName()); } }
The output is null, so don't use @NoArgsConstructor to modify the class if there are variables of @NonNull-modified members.
@ Required Args Constructor generates a constructor with one parameter for each field that needs special processing. All uninitialized final fields get a parameter, and any field marked @NonNull gets a parameter. These fields are not initialized where they are declared. For these fields marked @NonNull, special null compilation checks are generated. If the parameter of the field marked @NonNull is null, the constructor throws NullPointerException. The order of the parameters matches the order in which the fields are displayed in the class.
For example, in the following example, only fields decorated with @NonNull and final add constructors
@RequiredArgsConstructor public class RequiredArgsConstructorExample { @NonNull private int id; private final String name; private boolean human; }
The result is roughly the same.
public class RequiredArgsConstructorExample { @NonNull private int id; private final String name; private boolean human; public RequiredArgsConstructorExample(@NonNull int id, String name) { if (id == null) { throw new NullPointerException("id is marked @NonNull but is null"); } else { this.id = id; this.name = name; } } }
@ AllArgsConstructor: @AllArgsConstructor generates a constructor with one parameter for each field in the class. Fields labeled @NonNull cause null checks on these parameters.
@AllArgsConstructor public class AllArgsConstructorExample { private int id; private String name; private int age; }
Equivalent to automatically generate the following code
public AllArgsConstructorExample(int id, String name, int age) { this.id = id; this.name = name; this.age = age; }
Each of these annotations allows the use of alternative forms, where the generated constructor is always private and generates additional static factory methods containing private constructors, enabling this pattern by providing a staticName value for the annotation, @RequiredArgsConstructor (staticName = of). Look at the following example
@RequiredArgsConstructor(staticName = "of") @AllArgsConstructor(access = AccessLevel.PROTECTED) public class ConstructorExample<T> { private int x, y; @NonNull private T description; @NoArgsConstructor public static class NoArgsExample { @NonNull private String field; } }
It will become
public class ConstructorExample<T> { private int x, y; @NonNull private T description; private ConstructorExample(T description) { if (description == null) throw new NullPointerException("description"); this.description = description; } public static <T> ConstructorExample<T> of(T description) { return new ConstructorExample<T>(description); } @java.beans.ConstructorProperties({"x", "y", "description"}) protected ConstructorExample(int x, int y, T description) { if (description == null) throw new NullPointerException("description"); this.x = x; this.y = y; this.description = description; } public static class NoArgsExample { @NonNull private String field; public NoArgsExample() { } } }
Reference:
https://www.hellojava.com/a/74973.html
https://www.projectlombok.org/features/constructor