Recommended reading (Click to skip to reading)

1. SpringBoot content aggregation

2. Assemble interview questions

3. Design pattern content aggregation

4. Sorting algorithm content aggregation

5. Multi-threaded content aggregation

Lombok is an amazing Java class library that automatically generates annoying getters and setters in Java beans using annotations, It can also automatically generate Java-specific functions such as Logger, ToString, HashCode, Builder, etc., or functions that conform to design patterns, making your Java beans simpler and more beautiful.

Lombok’s idea of skipping boilerplate code and spending too much time on repetitive code is very advanced, and it’s an inevitable part of the Evolution of the Java language to do 80% of things 20% of the time.

Let’s take a look at lombok in action.

@Data

@data is a handy annotation that binds to @toString, @equalAndHashCode, @getter / @setter, and @requiredargsConstructor. In other words, @data generates all the boilerplate code normally associated with simple POJOs (Plain Old Java Objects) and beans, for example: Get all properties, set all non-inheritable properties, adapt toString, Equals, and HashCode implementations, initialize all final properties through constructors, and all non-final fields from initializers that do not use the @nonNULL flag, To ensure that the field is never null.

@data is like using the @toString, @equalAndHashCode, @getter, @setter, and @requiredargsConstructor annotations implicitly on a class. @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 add these annotations explicitly;

All generated getters/setters are public by default, and to override the access level, annotate the field or class with an explicit @setter@getter annotation. You can use this comment (by combining it with accessLevel.None) to disallow getters or setters.

All fields with transient tags are not treated as Hashcode and equals. All static fields are skipped completely (no generated methods are considered, and setters/getters are not created for them).

If a class already contains a method with the same name and argument count as any normally generated method, that method is not generated and no warnings or errors are raised.

For example: If you mark a method with equals, it will not be regenerated to equals, even though technically it could be a completely different method with different argument types. The same rules apply to constructors (any explicit constructor prevents @data from generating one), toString, equals, and all getters and setters.

You can use @ lombok. Experimental. Tolerate any constructor or method, in order to hide them in the lombok

Such as:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25Copy the code
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; }}Copy the code

This is equivalent to the following example without Lombok:

12 34 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 109 110 111 112 114 115 116 117 118, 119,Copy the code
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());
      returnresult; }}}Copy the code

@NonNull

You can use @nonnull to generate null-check for methods or constructors

If Lombok generates the entire method or constructor for you (for example, @data), Lombok always takes the various annotations on the field, often called @nonNULL, as a signal to generate a null check. Now, however, using Lombok’s own @lombok.nonnull on arguments results in inserting only null-check statements in your own methods or constructors.

Null-check statements look like the following

1
2
3
Copy the code
if(param == null){
  throw new NullPointerException("param is marked @NonNull but is null")}Copy the code

The null statement evaluates at the very beginning of the method

1, 2, 3, 4, 5, 6, 7, 8, 9Copy the code
public class NonNullExample { @Getter private String name; public NonNullExample(@NonNull String name){ this.name = name; }}Copy the code

This code with @nonNULL nulls is equivalent to the following code

12 3 4 5 6 7 8 9 10 11 12Copy the 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; }}Copy the code

@Getter & @Setter

You can automatically generate any Getter/Setter using @Getter and @Setter.

The default getter returns only the name of the field, getFoo() if the field name isFoo, and isFoo() if the field type is Boolean. If the field is foo, the default setter returns setFoo of type void and takes the same field as the property to assign to.

Methods generated using getters/setters default to the scope of public unless you specify AccessLevel. The access levels of AccessLevel are PUBLIC, PROTECTED, PACKAGE, and PRIVATE.

You can also use @getter / @setter on a class, in which case get and set methods are generated for all non-static properties in the class

You can also disable the generation of any get and set methods by setting accessLevel. NONE. This invalidates @data, @getter / @setter annotations.

12 3 4 5 6 7 8 9 10 11 12Copy the code
public class GetterSetterExample {
 
    @Setter
    @Getter
    private int age = 10;
 
    @Setter(AccessLevel.PROTECTED)
    private String name;
 
    @Getter(AccessLevel.PRIVATE)
    private String high;
}Copy the code

Is equivalent to

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24Copy the code
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() {returnhigh; }}Copy the code

@ToString

The @toString annotation replaces the implementation that generated the ToString () method, which by default prints your class name and each field in order, separated by commas.

Setting includeFieldNames = true enables the toString() method to print the attribute values and names for each field.

By default, all non-static attributes are printed. If you want to Exclude some fields, you need to set @toString. Exclude, or you can specify ToString(onlyExplicitlyIncluded = true) to specify which fields you want to use. Then use @toString. Include to mark each field to Include.

By setting callSuper to true, you can include the output of toString’s superclass implementation in the output. Note that the toString() implementation of java.lang.object doesn’t make any sense, so you probably won’t do it unless you want to extend another class.

You can also include the output of the method call in toString. Only instance (non-static) methods with no arguments can be included, for which use the @toString.include tag method.

You can change the names used to identify members using @toString. Include (name = “some other name”), and you can change the order in which members are printed by @toString. Include (rank = -1). Members with no defined rank default to level 0, members with higher rank are printed first, and members with the same priority are printed in the order they appear in the source file.

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31Copy the code
@toString public class ToStringExample {private static final int STATIC_VAR = 10; private String name; private String[] tags; private Shape shape = new Square(5, 10); @toString.Exclude private int id; public StringgetName() {
    returnthis.name; } // callSuper indicates whether toString() of the parent is extended, and // includeFieldNames indicates whether the attribute name @toString (callSuper =) is includedtrue, 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 {}
}Copy the code

Test the example above

1
2
Copy the code
ToStringExample toStringExample = new ToStringExample();
System.out.println(toStringExample);Copy the code

The output is as follows

1
Copy the code
ToStringExample(name=null, tags=null, shape=ToStringExample.Square(super=com.project.lombok.ToStringExample$Square@1b9e1916, width=5, height=10))Copy the code

Comment out callSuper = true, the test result is as follows

1
Copy the code
ToStringExample(name=null, tags=null, shape=ToStringExample.Square(width=5, height=10))Copy the code

As you can see from the output, no inner class information about Shape is printed if the parent class is not extended, and callSuper defaults to false

If you comment out includeFieldNames, the test result does not change, so includeFieldNames defaults to true

Change includeFieldNames = false and the test results look like this

1
Copy the code
ToStringExample(name=null, tags=null, shape=ToStringExample.Square(super=com.project.lombok.ToStringExample$Square@1b9e1916, 5, 10))Copy the code

As you can see from the output, if includeFieldNames = false, the field names in the Shape are not printed.

The example above decorated with the @toString annotation is equivalent to this code

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32Copy the 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 {}
}Copy the code

@EqualsAndHashCode

Any class definition can be annotated with @equalSandHashCode and have Lombok generate equals and hashCode methods for it. By default, will be used in static, the transient marker on the field of. But you can use @ EqualsAndHashCode Include or @ EqualsAndHashCode. Exclude tag type members use which fields to modify.

Or, you can use @ EqualsAndHashCode. Include and use @ EqualsAndHashCode (onlyExplicitlyIncluded = true) tag them to accurately specify the field, or you want to use the method.

This feature becomes dangerous if you apply @equalSandhashCode to extend another class. In general, automatically generating equals and hashcode methods on classes is not a good option, because superclasses also define fields that also require equals/hashcode methods. By setting callSuper to true, you can include the equals and HachCode methods of the superclass in the generated methods.

For hashCode, the result of super.hashcode includes the hash algorithm, and for equals, the generated method returns false if the superclass implementation does not think it is equal to the object passed in. Note that not all equals implementations handle this situation correctly. However, Lombok’s generated Equals implementation handles this correctly.

If you set callSuper to true when you do not extend the class (only any java.lang.Object class), you will get a compilation error, Lombok converts the generated equals() method and hashCode() implementation to be inherited from Object: only identical Object objects are equal to each other and have the same hashCode.

Not setting callSuper to true is a warning when you inherit from another class, because Lombok cannot generate for you an implementation of fields that take into account superclass declarations unless the parent class does not have the same properties. You need to write your own implementation classes or rely on the callSuper tool. You can also use lombok. EqualsAndHashCode. CallSuper configuration key.

Here’s an example

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26Copy the code
@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 StringgetName() {
        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 {}
}Copy the code

@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor

Lombok has three annotations to generate constructors, and let’s look at their usage instructions and examples

@noargsconstructor generates the constructor without arguments. Using the @noargsconstructor annotation alone will cause a compilation error if a final modified field is present and the final modified field is not initialized

Suggestions: You need to assign @noargsconstructor an attribute @noargsconstructor (force=true). Lombok adds an initial value for the above final field by default. Since id is of type int, the initial value for id is 0. Similarly, different types of fields also have false/null / 0 initialvalues, and certain Java constructs such as Hibernate and service provider interfaces require parameterless constructors. This annotation is primarily used in combination with @data or other constructors that generate the annotation.

One caveat here: @nonnull should not be used with @noargsconstructor

1
2
3
4
5
6
7
8
9
10
11
Copy the code
@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()); }}Copy the code

The output is NULL, so do not decorate a class with @noargsconstructor if a variable has a member decorated with @nonNULL

@requiredargsConstructor will generate a one-parameter constructor for each field requiring special handling. All final fields that are not initialized get a parameter, as do any fields marked @nonNULL. These fields are not initialized where they are declared. For these fields marked @nonNULL, a special NULL compilation check is generated. If the argument to a field marked @nonNULL is NULL, the constructor throws a NullPointerException. The order of the arguments matches the order in which the fields are displayed in the class.

For example, in the following example, only @nonNULL and final fields are added to constructors

1, 2, 3, 4, 5, 6, 7, 8, 9Copy the code
@RequiredArgsConstructor
public class RequiredArgsConstructorExample {
 
    @NonNull
    private int id;
    private final String name;
    private boolean human;
 
}Copy the code

So it’s going to look something like this

12 3 4 5 6 7 8 9 10 11 12 13 14 15Copy the code
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; }}}Copy the code

Constructor: @allargsconstructor generates a constructor with 1 argument for each field in the class. A field marked @nonNULL causes a null check for these parameters.

1, 2, 3, 4, 5, 6, 7, 8Copy the code
@AllArgsConstructor
public class AllArgsConstructorExample {
 
    private int id;
    private String name;
    private int age;
 
}Copy the code

The following code is automatically generated

One, two, three, four, fiveCopy the code
public AllArgsConstructorExample(int id, String name, int age) {
    this.id = id;
    this.name = name;
    this.age = age;
}Copy the code

Each of these annotations allows an alternate form, where the generated constructor is always private, and generates an additional static factory method containing the private constructor, enabling this pattern by providing a staticName value for the annotation, RequiredArgsConstructor (staticName = “of”). Look at the following example

1
2
3
4
5
6
7
8
9
10
11
Copy the code
@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; }}Copy the code

Will become

12 3 4 5 6 7 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28Copy the code
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() {}}}Copy the code

Article Reference:

www.hellojava.com/a/74973.htm… www.projectlombok.org/features/co…

See here, focus on one?