What is a Lombok

Lombok can simplify Java code in the form of simple annotations to improve developer productivity. For example, to create a Javabean in development, you need to add the corresponding getters/setters, constructors, equals, etc., and when there are too many properties, there will bea large number of getters/setters. Lombok can automatically generate getters/setters, constructors, equals, and other methods for properties at compile time via annotations. These methods are not present in the source code, but are present in the compile-generated byte files. This saves you the trouble of manually rebuilding the code and makes the code look cleaner.

Save the code amount of things can not miss, let’s actually operate below.

The specific implementation

Plug-in installation

To use Lombok, you need to install plug-ins so that no errors are reported at compile time.

Maven rely on

<! -- lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <scope>provided</scope>
</dependency>
Copy the code

@Data

The @data annotation on a class automatically generates getters/setters, toString, equals, hashCode methods for all attributes of the class. If it is a final property, no setter methods are generated for that property. @data is equivalent to @getter, @setter, @requiredargsConstructor, @toString, and @equalSandHashCode.

Official examples are as follows:

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 finalT value; }}Copy the code

If Lombok is not used, the implementation is as follows:

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(a) {
        return this.name;
    }

    void setAge(int age) {
        this.age = age;
    }

    public int getAge(a) {
        return this.age;
    }

    public void setScore(double score) {
        this.score = score;
    }

    public double getScore(a) {
        return this.score;
    }

    public String[] getTags() {
        return this.tags;
    }

    public void setTags(String[] tags) {
        this.tags = tags;
    }

    @Override
    public String toString(a) {
        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(! (oinstanceof 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(a) {
        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(a) {
            return this.name;
        }

        public T getValue(a) {
            return this.value;
        }

        @Override
        public String toString(a) {
            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(! (oinstanceof 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(a) {
            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

@Getter / @Setter

@getter / @setter can annotate classes and properties. Annotations on a class generate getter methods for all properties of the class and setter methods for all non-final properties of the class. Annotations On a property, you can generate getter/setter methods for the current property.

Official examples are as follows:

import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;

public class GetterSetterExample {

    @Getter
    @Setter
    private int age = 10;

    @Setter(AccessLevel.PROTECTED)
    private String name;

    @Override
    public String toString(a) {
        return String.format("%s (age: %d)", name, age); }}Copy the code

If Lombok is not used, the implementation is as follows:

public class GetterSetterExample {

    private int age = 10;

    private String name;

    @Override
    public String toString(a) {
        return String.format("%s (age: %d)", name, age);
    }

    public int getAge(a) {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    protected void setName(String name) {
        this.name = name; }}Copy the code

@EqualsAndHashCode

EqualsAndHashCode On a class, non-static and non-transient attributes are used by default to generate equals, canEqual, and hashCode methods. You can also exclude some attributes by using a exclude annotation.

Official examples are as follows:

import lombok.EqualsAndHashCode;

@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(a) {
        return this.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; }}}Copy the code

If Lombok is not used, the implementation is as follows:

import java.util.Arrays;

public class EqualsAndHashCodeExample {
    private transient int transientVar = 10;
    private String name;
    private double score;
    private Shape shape = new Square(5.10);
    private String[] tags;
    private int id;

    public String getName(a) {
        return this.name;
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) return true;
        if(! (oinstanceof EqualsAndHashCodeExample)) return false;
        EqualsAndHashCodeExample other = (EqualsAndHashCodeExample) o;
        if(! other.canEqual((Object)this)) return false;
        if (this.getName() == null? other.getName() ! =null:!this.getName().equals(other.getName())) return false;
        if (Double.compare(this.score, other.score) ! =0) return false;
        if(! Arrays.deepEquals(this.tags, other.tags)) return false;
        return true;
    }

    @Override
    public int hashCode(a) {
        final int PRIME = 59;
        int result = 1;
        final long temp1 = Double.doubleToLongBits(this.score);
        result = (result * PRIME) + (this.name == null ? 43 : this.name.hashCode());
        result = (result * PRIME) + (int) (temp1 ^ (temp1 >>> 32));
        result = (result * PRIME) + Arrays.deepHashCode(this.tags);
        return result;
    }

    protected boolean canEqual(Object other) {
        return other instanceof EqualsAndHashCodeExample;
    }

    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 boolean equals(Object o) {
            if (o == this) return true;
            if(! (oinstanceof Square)) return false;
            Square other = (Square) o;
            if(! other.canEqual((Object)this)) return false;
            if (!super.equals(o)) return false;
            if (this.width ! = other.width)return false;
            if (this.height ! = other.height)return false;
            return true;
        }

        @Override
        public int hashCode(a) {
            final int PRIME = 59;
            int result = 1;
            result = (result * PRIME) + super.hashCode();
            result = (result * PRIME) + this.width;
            result = (result * PRIME) + this.height;
            return result;
        }

        protected boolean canEqual(Object other) {
            return other instanceofSquare; }}}Copy the code

@ToString

The @toString annotation on a class generates ToString methods for the class. The default output is the class name, all attributes (in the order they are defined), separated by commas. By setting the includeFieldNames parameter to true, you can print the attribute names as well.

Official examples are as follows:

import lombok.ToString;

@ToString
public class ToStringExample {
    private static final int STATIC_VAR = 10;
    private String name;
    private Shape shape = new Square(5.10);
    private String[] tags;
    @ToString.Exclude
    private int id;

    public String getName(a) {
        return this.name;
    }

    @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; }}}Copy the code

If Lombok is not used, the implementation is as follows:

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(a) {
        return this.name;
    }

    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(a) {
            return "Square(super=" + super.toString() + ", width=" + this.width + ", height=" + this.height + ")"; }}@Override
    public String toString(a) {
        return "ToStringExample(" + this.getName() + "," + this.shape + "," + Arrays.deepToString(this.tags) + ")"; }}Copy the code

@NoArgsConstructor / @RequiredArgsConstructor / @AllArgsConstructor

Annotations on classes generate no-parameter constructors, partial parameter constructors, and full parameter constructors for classes. Lombok does not allow multiple parameter constructors to be overloaded.

Official examples are as follows:

import lombok.*;

@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
        privateString field; }}Copy the code

If Lombok is not used, the implementation is as follows:

public class ConstructorExample<T> {
    private int x, y;
    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 {
        private String field;

        public NoArgsExample(a) {}}}Copy the code

@NonNull

On a property, method, or constructor, Lombok generates a null check statement.

Official examples are as follows:

import lombok.NonNull;

public class NonNullExample extends Something {
    private String name;

    public NonNullExample(@NonNull Person person) {
        super("Hello");
        this.name = person.getName(); }}Copy the code

If Lombok is not used, the implementation is as follows:

public class NonNullExample extends Something {
    private String name;

    public NonNullExample(Person person) {
        super("Hello");
        if (person == null) {
            throw new NullPointerException("person is marked @NonNull but is null");
        }
        this.name = person.getName(); }}Copy the code

@Cleanup

The @cleanup annotation, in a local variable, ensures that a given resource is automatically cleaned up before the code execution path exits the current scope. Official examples are as follows:

import lombok.Cleanup;

import java.io.*;

public class CleanupExample {
    public static void main(String[] args) throws IOException {
        @Cleanup InputStream in = new FileInputStream(args[0]);
        @Cleanup OutputStream out = new FileOutputStream(args[1]);
        byte[] b = new byte[10000];
        while (true) {
            int r = in.read(b);
            if (r == -1) break;
            out.write(b, 0, r); }}}Copy the code

If Lombok is not used, the implementation is as follows:

import java.io.*;

public class CleanupExample {
    public static void main(String[] args) throws IOException {
        InputStream in = new FileInputStream(args[0]);
        try {
            OutputStream out = new FileOutputStream(args[1]);
            try {
                byte[] b = new byte[10000];
                while (true) {
                    int r = in.read(b);
                    if (r == -1) break;
                    out.write(b, 0, r); }}finally {
                if(out ! =null) { out.close(); }}}finally {
            if(in ! =null) { in.close(); }}}}Copy the code

@Log

On a class level, Lombok generates a logger called Log for the current class.

// @Log
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());

// @Log4j
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);

// @Log4j2
private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);

// @Slf4j
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
Copy the code

Official examples are as follows:

import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;

@Log
public class LogExample {

    public static void main(String... args) {
        log.severe("Something's wrong here"); }}@Slf4j
public class LogExampleOther {

    public static void main(String... args) {
        log.error("Something else is wrong here"); }}Copy the code

conclusion

Lombok’s strengths and weaknesses are obvious, as follows:

Advantages:

  • The ability to generate constructors, getters/setters, equals, HashCode, toString, and other methods through annotations improves development efficiency
  • Keep the code simple and don’t worry too much about the corresponding methods
  • Property changes also make it easier to regenerate new getters/setters for those properties

Disadvantages:

  • Plug-ins need to be installed
  • Overloading of multiple parameter constructors is not supported

But once you’ve tried it, it’s hard to stop using it.

The source code

Github.com/zhuqianchan…

Review past

  • Build backend frameworks from scratch – keep updating