This is the 19th day of my participation in the August More Text Challenge

preface

Among many programming languages at present, The Performance of Java language is still eye-catching. Whether it is enterprise server development or Android client development, Java language is the first choice for development language. Even in the field of big data development, Java language can also occupy a place, such as Hadoop, Spark, Flink big data, etc. Java, 24 years old, is a bit more verbose and complex to write than other languages. Lombok, a Java library, was created to greatly improve the efficiency and simplicity of Java development.

First let’s take a look at Lombok’s official description:

Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java. Never write another getter or equals method again, with one annotation your class has a fully featured builder, Automate your logging variables, and much more.

From the above illustration we can get a glimpse of Lombok, a Java library for editors and build tools that can enhance Java code by, for example, eliminating the need to write entity classesgetterMethod,equalsMethod but automatically generated, automatically generated log output variables and so on, reducing duplicate template code. With an overview of the Lombok framework’s capabilities, let’s take a look at Lombok’s annotations and see how they can help make Java code simpler and more efficient.

The main contents of this paper are as follows:

  • Lombok plug-in installation
  • Lombok uses annotations commonly

Environment support:

  • JDK 8
  • SpringBoot 2.1.4
  • Maven 3.6.0

The body of the

Lombok installation

Before using Lombok, you need to install it in the IDE you are using. Here, using IDEA as an example, the installation steps are very simple:

  • Go to File -> Settings -> Plugin -> Marketplace and search for Lombok

  • Select Lombok as the search result and click Install to Install.

  • Restart after the installation is complete.

Lombok based on Eclipse plug-in installation method here is not described in detail, the official also gives the corresponding documentation: projectlombok.org/setup/eclip…

After the Lombok plug-in is installed in the IDE, you can add Lombok’s dependencies to the POM.xml file for use.

<dependency> 
    <groupId>org.projectlombok</groupId> 
    <artifactId>lombok</artifactId> 
    <version>1.18.8</version> 
    <scope>provided</scope> 
</dependency> 
Copy the code

Note: The POM dependency sets the scope to Provided so that the Lombok library is not packaged into the program.

@Getter/@Setter

  • We typically write entity classes that provide getter and setter methods for no matter how many fields they have, as shown in the example user.java class

  • It’s not uncommon for an entity class to add or modify a field, and we have to deal with the adjustment separately, which is cumbersome and repetitive. If we use Lombok to provide @getter / @setter annotations to save us the maintenance of Getter and Setter methods, Lombok automatically generates getter and setter methods for the User class, and the resulting bytecode is the same, and the code we’re writing on User.java is just 7 lines:

@Getter
@Setter
public class User {
    private Integer id;
    private String username;
    private String password;
}
Copy the code

The testtests.java class usertests.java is used to test the testtests.java class.

public class UserTests {
    @Test
    public void test(a) {
        User user = new User();
        user.setUsername("one");
        user.setPassword("zxc123");
        Assert.assertEquals(user.getUsername(), "one");
        Assert.assertEquals(user.getPassword(), "zxc123"); }}Copy the code

The @getter / @setter annotation can be used not only on a class, but also on a field to indicate that Getter/ Setter methods are automatically generated for that field.

@Getter
@Setter
private String password;
Copy the code

The difference between using the annotation on a class and on a field is that if the annotation is used on a class, it only applies to the non-static fields of that class.

One thing to note is that if the @Getter annotation modifies a Boolean variable, it generates the Getter method signature of isXXX, not getXXX.

In addition, @getter / @setter also provides the access control property lombok.Accesslevel Value (), which defaults to PUBLIC, while the other options are enumerated types: MODULE, PROTECTED, PACKAGE, PRIVATE

@NonNull

As the name implies, @nonNULL is used to mark a field or parameter in a class that cannot be null. A NullPointException (NPE) is raised wherever this field is used. For example:

public class User {
    private Integer id;
    private String username;
    private String password;

    public User(Integer id, @NonNull String username, @NonNull String password) {
        this.id = id;
        this.username = username;
        this.password = password; }}Copy the code

Using the @nonNULL annotation we can get the decomcompiled bytecode information as follows, which is the final code Lombok generated for us:

public class User {
    private Integer id;
    private String username;
    private String password;

    public User(Integer id, @NonNull String username, @NonNull String password) {
        if (username == null) {
            throw new NullPointerException("username is marked non-null but is null");
        } else if (password == null) {
            throw new NullPointerException("password is marked non-null but is null");
        } else {
            this.id = id;
            this.username = username;
            this.password = password; }}}Copy the code

Constructor annotation

Again, a common scenario, writing a constructor method for an entity class, Lombok provides three different constructor annotations, @noargsconstructor / @allargsconstructor / @requiredargsconstructor, which are described below for handling the constructor methods.

  • @noargsconstructor generates a constructor method with no arguments for the entity class

  • @allargsconstructor generates constructor methods for entity classes that take arguments other than static modified fields.

  • @requiredargsConstructor generates constructor methods for entity classes specifying fields that need to be final, or @nonNULL.

    @RequiredArgsConstructor
    public class User3 {
        private Integer id;
        private final String username;
        @NonNull
        private String password;
    }
    Copy the code

    User3 User3 = new User3(” User3 “, “zxc123”);

@ToString

@toString automatically generates an easy-to-read ToString method for the class, with property names and values for non-static fields, making it easy to print in your daily development.

@Getter
@Setter
@AllArgsConstructor
@ToString
public class User2 {
    private Integer id;
    private String username;
    private String password;
}
Copy the code

Finally compiled into bytecode, decompilation results are as follows:

public class User2 {
    private Integer id;
    private String username;
    private String password;
    / / save the setter/getter
    public String toString(a) {
        return "User2(id=" + this.getId() + ", username=" + this.getUsername() + ", password=" + this.getPassword() + ")"; }}Copy the code

In addition, the @toString annotation allows you to set the logging output of specified fields and which fields do not need to appear in the ToString method. Use @toString. Exclude to Exclude fields that do not need to be included in ToString. Use @toString. Include to Exclude fields that need to be included in ToString.

@Getter
@Setter
@AllArgsConstructor
@ToString
public class User2 {
    @ToString.Exclude
    private Integer id;
    @ToString.Include
    private String username;
    @ToString.Include
    private String password;
}
Copy the code

The log effect of the User2 object is User2(username= User2, password=zcx123).

@EqualsAndHashCode

The @equalSandHashCode annotation is used to automatically override equals and hashCode methods based on non-static fields owned by the class, so that we can compare objects. Like @toString, @equalSandhashCode can also use fields that need to be compared and exclude fields that do not need to be compared, as shown in the following example:

@Getter
@Setter
@AllArgsConstructor
@ToString
@EqualsAndHashCode
public class User4 {
    @EqualsAndHashCode.Exclude
    private Integer id;
    @EqualsAndHashCode.Include
    private String username;
    @EqualsAndHashCode.Exclude
    private String password;
}
Copy the code

After writing the entity class code, we write a test method to test the effect:

@Test
public void testEqual(a) {
    User4 user4 = new User4(1."user4"."zxc");
    User4 user4_2 = new User4(1."user4"."123");
    Assert.assertEquals(user4, user4_2); // ture
}
Copy the code

@Data/@Value

The @data / @value annotation, which provides more comprehensive code generation capabilities, is equivalent to the following annotations

@Getter
@Setter
@AllArgsConstructor
@ToString
@EqualsAndHashCode
Copy the code

Both annotations can only be used on classes, unlike @data, which is used to modify immutable classes. The @data annotation can be used directly in general entity classes without specific restrictions.

@Builder

@Builder is a very powerful annotation that provides an API for building objects based on the Builder pattern. Use the @Builder annotation to automatically generate the Builder () method for our entity class, assign fields directly to the field name method, and finally build an entity object using the Build () method.

@Data
@Builder
public class User6 {
    private Integer id;
    private String username;
    private String password;
}

@Test
public void testBuilder(a) {
    User6 user6 = User6.builder().id(1).username("user6").password("zxc123").build();
    log.warn("testLog: {}", user6); // User6(id=1, username=user6, password=zxc123)
}
Copy the code

It is important to note that @Builder does not support the generation of superclass fields. When an entity class has a superclass, @Builder can only generate the field construction method of the current class. Lombok provides a new annotation @superBuilder to address the need for superclass field methods. Here’s how to use the @SuperBuilder annotation:

@SuperBuilder
@Getter 
@Setter
public class Parent {
   private int id;
   private String name;
}

@SuperBuilder
@Data
public class Child extends Parent {
    private String childName;
}
Copy the code

Call example:

Child child = Child.builder().id(1).name("Parent class name").childName("Subclass name").build();
System.out.println(child.getId());
Copy the code

The Builder () method cannot be found because the Lombok Plugin has not yet been updated to support @superBuilder.

Also can refer to this way to deal with the situation of the inheritance: reinhard. Codes / 2015/09/16 /…

Log notes

Lombok also provides annotations to automatically generate Logger objects and gracefully output logs, just by using logging annotations such as @log on the class. Lombok supports several logging frameworks, of course, and provides the following annotations:

  • @commonslog Equivalent effect: private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);

  • @flogger private static final com.google.common.flogger.FluentLogger log = com.google.common.flogger.FluentLogger.forEnclosingClass();

  • @ JBosLog equivalent effect: private static final org. Jboss. Logging. The Logger log = org. Jboss. Logging. The Logger. GetLogger (LogExample. Class);

  • @log equivalent effect: private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());

  • @ Log4j equivalent effect: private static final. Org. Apache Log4j. Logger log = org. Apache.. Log4j Logger. GetLogger (LogExample. Class);

  • @log4j2 equivalent effect: private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);

  • @ Slf4j equivalent effect: private static final org. Slf4j. The Logger log = org. Slf4j. LoggerFactory. GetLogger (LogExample. Class);

  • XSlf4j equivalent effect: private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);

The following code uses the @slf4J annotation to log:

@Slf4j
public class UserTests {
	    / /...
    @Test
    public void testLog(a) {
        User5 user5 = new User5();
        user5.setId(1);
        user5.setUsername("user5");
        user5.setPassword("zxc123");
        log.warn("testLog: {}", user5); 
   / / 21:57:15. 488. [the main] WARN com one. Learn. Lombok. UserTests - testLog: User5 (id = 1, the username = User5, password = zxc123)}}Copy the code

@Cleanup

Cleanup is used to flag resource object variables that need to be released for Cleanup operations, such as FileInputStream, FileOutputStream, etc. After this flag, the resource object is automatically closed and cleaned up when it is finished. In fact, Lombok works like the Java7 try with Resource feature, shielding us from template code that closes resources. Here’s an example of how to use @cleanup:

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

Decompressing the bytecode generated by the cleanupexample.java compilation yields the following result:

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

@SneakyThrows

The @sneakythrows is mainly used to secretly throw checked exceptions without the throws keyword. It is the throw operation that is omitted when exception throwing is required in our normal development. The following is an example code using @Sneakythrows:

public class SneakyThrowsExample implements Runnable {
  @SneakyThrows(UnsupportedEncodingException.class)
  public String utf8ToString(byte[] bytes) {
    return new String(bytes, "UTF-8");
  }
  
  @SneakyThrows
  public void run(a) {
    throw newThrowable(); }}Copy the code

Finally compiled into bytecode, decompilation results are as follows:

public class SneakyThrowsExample implements Runnable {
    public SneakyThrowsExample(a) {}public String utf8ToString(byte[] bytes) {
        try {
            return new String(bytes, "UTF-8");
        } catch (UnsupportedEncodingException var3) {
            throwvar3; }}public void run(a) {
        try {
            throw new Throwable();
        } catch (Throwable var2) {
            throwvar2; }}}Copy the code

val/var

Val /var is used to modify local variables. With this annotation modifier, the type of the variable is automatically inferred from the expression to the right of the equals sign. This feature is borrowed from the automatic type inference feature of many programming languages. The difference between val and var is that val modifies immutable variables and var modifies mutable variables. When a variable modified by val is reassigned, the compiler raises an exception: Error: Java: could not assign a value to the final variable X. The actual usage is also relatively simple, can refer to the following code:

@Slf4j
public class VarValExample {
    public static void main(String[] args) {
        val text = "abc";
								        // text = "1"; // Error: Java: could not assign a value to the final variable text.
        var num = 1;
        num = 2;
        log.info("text:{},num:{}", text, num); // text:abc,num:2}}Copy the code

conclusion

So far, we’ve learned about 80% of Lombok’s common annotations, which are more than enough to be used in our daily development. Start experimenting with Lombok and you’ll start to see the efficiency and elegance of your code.

reference

  • Project Lombok: projectlombok.org/

  • Stackabuse.com/project-lom…

  • Project Lombok: Reducing Java Boilerplate Code: stackabuse.com/project-lom…

  • Summary of Lombok commonly used the use of annotations: segmentfault.com/a/119000001…

  • Lombok @Builder with Inheritance: www.baeldung.com/lombok-buil…

  • Blog.didispace.com/java-lombok…

  • Lombok ‘s @ Builder annotation and inheritance: reinhard. Codes / 2015/09/16 /…

  • Lombok: Making JAVA code more elegant: blog.didispace.com/java-lombok…

  • About Lombok: mp.weixin.qq.com/s?__biz=MzI…