Programmer's Java Cheat Sheets 10: Lombok

  • Tutorial
image

Lombok is a project to add additional functionality to Java by changing the source code before Java compilation.

In fact, the Lombok project allows you to get rid of the verbosity of Java in most cases and stop writing huge sheets of code from getters, setters, equals, hashcode and toString (yes they are usually generated by the IDE, but the programmer has to read and change anyway), as a result of Java, it becomes almost as concise as Kotlin, Scala or C #.

Which is especially pleasing, Lombok is very simple and easy to add to your project. If you, like me, like the KISS principle, then I advise you to look at Lombok.

I also recommend looking at other articles in the series , such as the latest Java SE8 cheat sheet

Adding to projects is very simple, just add the usual dependencies:

More details ...
Maven :

org.projectlomboklombok1.16.18

It is also possible (but it is not necessary to add a plug-in for the operation of static compilers, if you need to analyze the code after compiling Lombok), see here

Gradle

plugins {
    id 'net.ltgt.apt' version '0.10'
}
dependencies {
	compileOnly 'org.projectlombok:lombok:1.16.18'
	apt "org.projectlombok:lombok:1.16.18"
}

There are also plugins for Idea , Eclipse , etc. If you build Gradle or Maven, then it will be built without these plugins, but Idea / Eclipse will probably show errors when analyzing the code.

Commands and annotations:
Table
TitleDescriptionLombok example
Plain Java Example
@NonNullhandling variables
that should not receive null
public Example(@NonNull P p) {
 super("Hello");
 this.name = p.getName();
}

public Example(@NonNull P p) {
  super("Hello");
  if (p == null) {
    throw new NullPointerException("p");
  }
  this.name = p.getName();
}

@Getter /
@Setter
easy creation of getters and
setters
@Getter 
@Setter 
private int age = 10;

private int age = 10;
public int getAge() {
 return age;
} 
public void setAge(int age) {
  this.age = age;
}

@ToStringdefinition of annotation before the class,
to implement the standard toString method
@ToString(exclude="f")
public class Example

public class Example {
  @Override 
  public String toString() {
    return ...;
  }

@EqualsAndHashCode easy creation of Equals and HashCode methods
@EqualsAndHashCode(
   exclude={"id1", "id2"})
public class Example {

public class Example {
  ...
  @Override 
  public boolean equals(Object o) {
     ...
  }
  @Override 
  public int hashCode() {
     ...
  }

@NoArgsConstructor,
@RequiredArgsConstructor,
@AllArgsConstructor
create an empty constructor, a
constructor that includes all final fields,
or a constructor that includes all possible fields
@RequiredArgsConstructor(
     staticName = "of"
)
@AllArgsConstructor(
    access = AccessLevel.PROTECTED
)
public class E {

public class E {
 private E(T description) {
     ...
 }
 public static E of(
     T description
) {
   return new E(description);
 } 

@Data generation of all utility methods,
immediately replaces the @ToString, @EqualsAndHashCode,
Getter , Setter , @RequiredArgsConstructor commands
@Data
public class Example { 
  private final String name;
  private int age;
}

A lot of code
public class Example {
  private final String name;
  private int age;
  public Example(
     String name
  ) {
    this.name = name;
  }
  public String getName() {
    return this.name;
  }
  void setAge(int age) {
    this.age = age;
  }
  public int getAge() {
    return this.age;
  }
  @Override
 public String toString() {
    return ...;
  }
  @Override 
  public boolean equals(
    Object o
  ) {
    ....
  }
  @Override 
  public int hashCode() {
    ...
  }


@Value creation of immutable classes,
analogous to Data, but for immutable classes
@Value
public class Example { 
  private final String name;
  private int age;
}

A lot of code
public class Example {
  private final String name;
  private final int age;
  public Example(
    String name, int age
) {
    this.name = name;
    this.age = age;
  }
  public String getName() {
    return this.name;
  }
  public int getAge() {
    return this.age;
  }
  @Override
 public String toString() {
    return ...;
  }
  @Override 
  public boolean equals(
     Object o
  ) {
    ....
  }
  @Override 
  public int hashCode() {
    ...
  }


@Builder implementation of the bulder,
Singular pattern - used for objects in a
single copy (adding an item
to the collection, etc.)  
@Builder
public class Example {
  private String name;
  private int age;
  @Singular 
  private Set occupations;
}

a lot of code
public class Example {
  private String name;
  private int age;
  private Set occupations;
  Example(
    String name, 
    int age, 
   Set occupations
 ) {
    this.name = name;
    this.age = age;
    this.occupations = occupations;
  }
  public static ExampleBuilder builder() {
    return new ExampleBuilder();
  }
  public static class ExampleBuilder {
    private String name;
    private int age;
    private ArrayList<> occupations;
    ExampleBuilder() {
    }
    public ExampleBuilder name(
       String name
    ) {
      this.name = name;
      return this;
    }
    public ExampleBuilder age(
      int age
    ) {
      this.age = age;
      return this;
    }
    public ExampleBuilder occupation(
      String occupation
   ) {
      if (this.occupations == null) {
        this.occupations = 
          new ArrayList();
      }
      this.occupations.add(occupation);
      return this;
    }
   ...
    public Example build() {
      Set occupations = ...;
      return new Example(name, age, occupations);
    }
    @java.lang.Override
    public String toString() {
      ...
    }
  }
}


@SneakyThrows wrapper of checked exceptions
@SneakyThrows (
UnsupportedEncodingException.class)
public String utf8ToString (byte [] bytes) {
return new String (bytes, "UTF-8");
}
public String utf8ToString(byte[] bytes) {
    try {
      return new String(bytes, "UTF-8");
    } catch (UnsupportedEncodingException e) {
      throw Lombok.sneakyThrow(e);
    }
 }

@Synchronized simple creation of synchronized blocks
private final Object readLock = new Object();
@Synchronized
public static void hello() {
    ...;
 }
 @Synchronized
 public int answerToLife() {
   ...
 }
 @Synchronized("readLock")
 public void foo() {
    ...
 }

A lot of code
private static final Object $LOCK = new Object[0];
private final Object $lock = new Object[0];
private final Object readLock = new Object();
public static void hello() {
  synchronized($LOCK) {
    ...
   }
}
public int answerToLife() {
  synchronized($lock) {
    ...
   }
}
public void foo() {
   synchronized(readLock) {
      ...
   }
}


@Log Adding log initialization
also allows you to choose the type of logger: @CommonsLog,
@JBossLog, Log , @ Log4j, @ Log4j2, @ Slf4j, @ XSlf4j
@Slf4j
public class Example {
  public static void main(String... args) {
    log.error("error");
  }

public class Example {
  private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExampleOther.class);
  public static void main(String... args) {
    log.error("error");
  }

Valsimple creation of a final
variable with type inference,
that is, the very val
argued about
val map = new HashMap();
for (val entry : map.entrySet()) {
      ...
}

final HashMap map = new HashMap();
...
for (final Map.Entry entry : map.entrySet()) {
      ...
}

@CleanupA simple definition of resources,
so that they automatically close
after the code ends.
(not so relevant when using
try with resources)
@Cleanup InputStream in = new FileInputStream(args[0]);
@Cleanup OutputStream out = new FileOutputStream(args[1]);
...

InputStream in = new FileInputStream(args[0]);
    try {
      OutputStream out = new FileOutputStream(args[1]);
      try {
        ...
      } finally {
        if (out != null) {
          out.close();
        }
      }
    } finally {
      if (in != null) {
        in.close();
      }
    }





If the table seems to be poorly read, just take turns
Name: @NonNull
Description: handling variables
that should not receive null
Lombok code:
public Example(@NonNull P p) {
 super("Hello");
 this.name = p.getName();
}
Normal Java code:
public Example(@NonNull P p) {
  super("Hello");
  if (p == null) {
    throw new NullPointerException("p");
  }
  this.name = p.getName();
}



Name: Getter /
Setter
Description: easy creation of getters and
setters
Lombok code:
@Getter 
@Setter 
private int age = 10;
Normal Java code:
private int age = 10;
public int getAge() {
 return age;
} 
public void setAge(int age) {
  this.age = age;
}



Name: @ToString
Description: defining the annotation before the class,
for implementing the standard toString method
Lombok code:
@ToString(exclude="f")
public class Example
Normal Java code:
public class Example {
  @Override 
  public String toString() {
    return ...;
  }



Name: @EqualsAndHashCode
Description: easy creation of Equals and HashCode methods
Lombok code:
@EqualsAndHashCode(
   exclude={"id1", "id2"})
public class Example {
Normal Java code:
public class Example {
  ...
  @Override 
  public boolean equals(Object o) {
     ...
  }
  @Override 
  public int hashCode() {
     ...
  }



Name:
@NoArgsConstructor,
@RequiredArgsConstructor,
@AllArgsConstructor
Description: create an empty constructor, a
constructor that includes all final fields,
or a constructor that includes all possible fields
Lombok code:
@RequiredArgsConstructor(
     staticName = "of"
)
@AllArgsConstructor(
    access = AccessLevel.PROTECTED
)
public class E {
Normal Java code:
public class E {
 private E(T description) {
     ...
 }
 public static E of(
     T description
) {
   return new E(description);
 } 



Name: Data
Description: generation of all utility methods,
immediately replaces the @ToString, @EqualsAndHashCode,
Getter , Setter , @RequiredArgsConstructor commands
Lombok code:
@Data
public class Example { 
  private final String name;
  private int age;
}



public class Example {
  private final String name;
  private int age;
  public Example(
     String name
  ) {
    this.name = name;
  }
  public String getName() {
    return this.name;
  }
  void setAge(int age) {
    this.age = age;
  }
  public int getAge() {
    return this.age;
  }
  @Override
 public String toString() {
    return ...;
  }
  @Override 
  public boolean equals(
    Object o
  ) {
    ....
  }
  @Override 
  public int hashCode() {
    ...
  }




Name: Value
Description: creating immutable classes,
an analogue of Data, but for immutable classes
Lombok code:
@Value
public class Example { 
  private final String name;
  private int age;
}


Normal Java code:
public class Example {
  private final String name;
  private final int age;
  public Example(
    String name, int age
) {
    this.name = name;
    this.age = age;
  }
  public String getName() {
    return this.name;
  }
  public int getAge() {
    return this.age;
  }
  @Override
 public String toString() {
    return ...;
  }
  @Override 
  public boolean equals(
     Object o
  ) {
    ....
  }
  @Override 
  public int hashCode() {
    ...
  }




Name: Builder
Description: implementation of the bulder pattern,
Singular - used for objects in a
single copy (adding an item
to the collection, etc.)  
Lombok code:
@Builder
public class Example {
  private String name;
  private int age;
  @Singular 
  private Set occupations;
}


Normal Java code:
public class Example {
  private String name;
  private int age;
  private Set occupations;
  Example(
    String name, 
    int age, 
   Set occupations
 ) {
    this.name = name;
    this.age = age;
    this.occupations = occupations;
  }
  public static ExampleBuilder builder() {
    return new ExampleBuilder();
  }
  public static class ExampleBuilder {
    private String name;
    private int age;
    private ArrayList<> occupations;
    ExampleBuilder() {
    }
    public ExampleBuilder name(
       String name
    ) {
      this.name = name;
      return this;
    }
    public ExampleBuilder age(
      int age
    ) {
      this.age = age;
      return this;
    }
    public ExampleBuilder occupation(
      String occupation
   ) {
      if (this.occupations == null) {
        this.occupations = 
          new ArrayList();
      }
      this.occupations.add(occupation);
      return this;
    }
   ...
    public Example build() {
      Set occupations = ...;
      return new Example(name, age, occupations);
    }
    @java.lang.Override
    public String toString() {
      ...
    }
  }
}




Name: @SneakyThrows
Description: wrapper of checked exceptions
Lombok code:

@SneakyThrows (
UnsupportedEncodingException.class)
public String utf8ToString (byte [] bytes) {
return new String (bytes, "UTF-8");
}

Lombok code:
public String utf8ToString(byte[] bytes) {
    try {
      return new String(bytes, "UTF-8");
    } catch (UnsupportedEncodingException e) {
      throw Lombok.sneakyThrow(e);
    }
 }



Name: @Synchronized
Description: simple creation of synchronized blocks
Lombok code:
private final Object readLock = new Object();
@Synchronized
public static void hello() {
    ...;
 }
 @Synchronized
 public int answerToLife() {
   ...
 }
 @Synchronized("readLock")
 public void foo() {
    ...
 }


Normal Java code:
private static final Object $LOCK = new Object[0];
private final Object $lock = new Object[0];
private final Object readLock = new Object();
public static void hello() {
  synchronized($LOCK) {
    ...
   }
}
public int answerToLife() {
  synchronized($lock) {
    ...
   }
}
public void foo() {
   synchronized(readLock) {
      ...
   }
}




Name: Log
Description: adding the initialization of logging,
also allows you to choose the type of logger: @CommonsLog,
@JBossLog, Log , @ Log4j, @ Log4j2, @ Slf4j, @ XSlf4j
Lombok code:
@Slf4j
public class Example {
  public static void main(String... args) {
    log.error("error");
  }
Normal Java code:
public class Example {
  private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExampleOther.class);
  public static void main(String... args) {
    log.error("error");
  }



Val is a simple creation of a final
variable with type inference,
that is, the very val
argued about
val map = new HashMap();
for (val entry : map.entrySet()) {
      ...
}

final HashMap map = new HashMap();
...
for (final Map.Entry entry : map.entrySet()) {
      ...
}



Name: @Cleanup
Description: A simple definition of resources,
so that they are automatically closed
after the end of the code.
(not so relevant when using
try with resources)
Lombok code:
@Cleanup InputStream in = new FileInputStream(args[0]);
@Cleanup OutputStream out = new FileOutputStream(args[1]);
...
Normal Java code:
InputStream in = new FileInputStream(args[0]);
    try {
      OutputStream out = new FileOutputStream(args[1]);
      try {
        ...
      } finally {
        if (out != null) {
          out.close();
        }
      }
    } finally {
      if (in != null) {
        in.close();
      }
    }


Also popular now: