Introduction to the
Lombok is a handy tool, just like Google Guava. Can be used to help developers eliminate Java’s verbose code, especially for simple Java objects (POJOs). It does this through annotations.
By implementing Lombok in a development environment, developers can save a lot of time building methods like hashCode() and equals() and sorting various accessors and mutators.
IntelliJ Lombok installation
-
Install via IntelliJ’s plug-in center
-
Install Plugin
-
Import lombok package
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.168.</version> </dependency> Copy the code
Lombok explanatory Notes
val
: used before a local variable, which is equivalent to declaring the variable final@NonNull
NullPointerException (NPE) NullPointerException (NPE) NullPointerException@Cleanup
: Automatically manages resources before local variables, cleans up resources before exiting within the current variable scope, and automatically generates try-finally code to close the stream@Getter/@Setter
: for properties, you no longer have to write your own setters and getters, and you can also specify access scopes@ToString
: ToString(exclude= “id”); toString (exclude= “id”); toString (exclude= “id”) Or @toString (callSuper=true, includeFieldNames=true) calls the ToString method of the parent class, containing all attributes@EqualsAndHashCode
The equals method and hashCode method are automatically generated for the class@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor
For classes, it automatically generates no-argument constructors that take all arguments and constructors that take all @nonNULL attributes as arguments. Specifying staticName = “of” also generates a static factory method that returns the class object, which is much more convenient than using the constructor@Data
This is a class equivalent to using @ToString, @EqualSandHashCOD-e, @getter, @setter, and @RequiredargsConstrutor at the same time, which is a useful construtor for POJO classes@Value
Used in classes, the immutable form of @data is equivalent to adding a final declaration to a property, providing getter methods instead of setter methods@Builder
: For classes, constructors, and methods, providing you with the complex Builder APIs, Lets you call Person.builder().name(“Adam Savage”).city(“San Francisco”).Job (“Mythbusters”).job(“Unchained “) Reaction”).build(); Refer to Builder for more instructions@SneakyThrows
: Automatically throws checked exceptions without explicitly using throws statements on methods@Synchronized
: The LOCK object is a private attribute LOCK, while the Synchronized keyword LOCK object in Java is this. Locking on this or its own class object has side effects. That is, you cannot prevent uncontrolled code from locking this or class objects, which could cause race conditions or other thread errors@Getter(lazy=true)
: can replace the classic Double Check Lock boilerplate code@Log
: Generates different types of log objects based on different annotations, but the instance name is log, and there are six optional implementation classes-
@CommonsLog
Creates log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);@Log
Creates log = java.util.logging.Logger.getLogger(LogExample.class.getName());@Log4j
Creates log = org.apache.log4j.Logger.getLogger(LogExample.class);@Log4j2
Creates log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);@Slf4j
Creates log = org.slf4j.LoggerFactory.getLogger(LogExample.class);@XSlf4j
Creates log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);
Lombok code examples
Val sample
public static void main(String[] args) {
val sets = new HashSet<String>();
val lists = new ArrayList<String>();
val maps = new HashMap<String, String>();
//=> Equivalent to the following
final Set<String> sets2 = new HashSet<>();
final List<String> lists2 = new ArrayList<>();
final Map<String, String> maps2 = new HashMap<>();
}
Copy the code
@ NonNull sample
public void notNullExample(@NonNull String string) {
string.length();
}
/ / = > equivalent
public void notNullExample(String string) {
if (string! = null) {string.length();
} else {
throw new NullPointerException("null"); }}Copy the code
@ the Cleanup examples
public static void main(String[] args) {
try {
@Cleanup InputStream inputStream = new FileInputStream(args[0]);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
/ / = > equivalent
InputStream inputStream = null;
try {
inputStream = new FileInputStream(args[0]);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if(inputStream ! = null) { try { inputStream.close(a); } catch (IOException e) { e.printStackTrace(); }}}}Copy the code
@ Getter / @ Setter example
@Setter(AccessLevel.PUBLIC)
@Getter(AccessLevel.PROTECTED)
private int id;
private String shap;
Copy the code
@ ToString sample
@ToString(exclude = "id", callSuper = true, includeFieldNames = true)
public class LombokDemo {
private int id;
private String name;
private int age;
public static void main(String[] args) {
LombokDemo(super=LombokDemo@48524010, name=null, age=0)
System.out.println(newLombokDemo()); }}Copy the code
@ EqualsAndHashCode sample
@EqualsAndHashCode(exclude = {"id"."shape"}, callSuper = false)
public class LombokDemo {
private int id;
private String shap;
}
Copy the code
NoArgsConstructor, @requiredargsconstructor and @allargsconstructor examples
@NoArgsConstructor
@RequiredArgsConstructor(staticName = "of")
@AllArgsConstructor
public class LombokDemo {
@NonNull
private int id;
@NonNull
private String shap;
private int age;
public static void main(String[] args) {
new LombokDemo(1."circle");
// Use the static factory method
LombokDemo.of(2."circle");
// No arguments
new LombokDemo();
// Contains all parameters
new LombokDemo(1."circle".2); }}Copy the code
@ the Data sample
import lombok.Data;
@Data
public class Menu {
private String shopId;
private String skuMenuId;
private String skuName;
private String normalizeSkuName;
private String dishMenuId;
private String dishName;
private String dishNum;
// Default threshold
private float thresHold = 0;
/ / the new threshold
private float newThresHold = 0;
/ / total score
private float totalScore = 0;
}
Copy the code
@ the Value sample
@Value
public class LombokDemo {
@NonNull
private int id;
@NonNull
private String shap;
private int age;
/ / equivalent to
private final int id;
public int getId() {
returnthis.id; }... }Copy the code
@ Builder sample
@Builder
public class BuilderExample {
private String name;
private int age;
@Singular
private Set<String> occupations;
public static void main(String[] args) {
BuilderExample test = BuilderExample.builder().age(11).name("test").build(); }}Copy the code
@ SneakyThrows sample
import lombok.SneakyThrows;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
public class Test {
@SneakyThrows()
public void read() {
InputStream inputStream = new FileInputStream("");
}
@SneakyThrows
public void write() {
throw new UnsupportedEncodingException();
}
/ / equivalent to
public void read() throws FileNotFoundException {
InputStream inputStream = new FileInputStream("");
}
public void write() throws UnsupportedEncodingException {
throw newUnsupportedEncodingException(); }}Copy the code
@ Synchronized sample
public class SynchronizedDemo {
@Synchronized
public static void hello() {
System.out.println("world");
}
/ / equivalent to
private static final Object $LOCK = new Object[0];
public static void hello() {
synchronized ($LOCK) {
System.out.println("world"); }}}Copy the code
@Getter(lazy = true)
public class GetterLazyExample {
@Getter(lazy = true)
private final double[] cached = expensive();
private double[] expensive() {
double[] result = new double[1000000];
for (int i = 0; i < result.length; i++) {
result[i] = Math.asin(i);
}
returnresult; }}// Equivalent to the following:
import java.util.concurrent.atomic.AtomicReference;
public class GetterLazyExample {
private final AtomicReference<java.lang.Object> cached = new AtomicReference<>();
public double[] getCached() {
java.lang.Object value = this.cached.get();
if (value == null) {
synchronized (this.cached) {
value = this.cached.get();
if(value == null) { final double[] actualValue = expensive(); value = actualValue == null ? this.cached : actualValue; this.cached.set(value); }}}return (double[]) (value == this.cached ? null : value);
}
private double[] expensive() {
double[] result = new double[1000000];
for (int i = 0; i < result.length; i++) {
result[i] = Math.asin(i);
}
returnresult; }}Copy the code
Lombok annotations (a little hard to understand and ignore)
Those of you who are familiar with Java custom annotations have already guessed that Lombok relies on the Pluggable Java Custom Annotation Processing API (JSR 269: Pluggable Annotation Processing API) for its implementation
The “Annotation Processor” is used during the Javac compilation phase to preprocess custom annotations to produce the “Class file” being executed on the JVM. Decompiling Lombok annotated class files should be easy for those interested. Its general implementation principle diagram is as follows:
As you can see from the schematic above, Annotation Processing is the step the compiler takes between parsing Java source code and generating Class files. The specific execution flow of Lombok plug-in is as follows:
As you can see from the diagram of Lombok’s execution above, after Javac has been parsed into an AST abstract syntax tree, Lombok dynamically modifies the AST to add new nodes (that is, the code Lombok generates for custom annotations) based on its own annotation processor. Finally, a JVM executable bytecode Class file is generated through analysis.
Custom annotations using Annotation Processing are modified at compile time, while reflection in the JDK is modified dynamically at run time. Reflection is more flexible but incurs a higher performance penalty than Annotation Processing.
A deeper understanding of the details of Lombok plug-ins is required, and looking up the source code yourself is more than necessary. Those who are keen on open source framework code can download Lombok’s source code project from Github for local reading and debugging. Below is a screenshot of the Lombok project source code:
Those familiar with the JSR 269: Pluggable Annotation Processing API can see the AnnotationProcessor class in the engineering class diagram as an entry point for Lombok’s custom Annotation Processing.
The two important methods in this class are init and process.
In the init method, the internal classes defined in the AnnotationProcessor class (JavacDescriptor, EcjDescriptor) are first registered in the list of ProcessorDescriptor type definitions. Among them, the internal static class – JavacDescriptor. When the load will be lombok javac. Apt. LombokProcessor object instantiation and register this class.
In the LombokProcessor, the Process method runs the corresponding handler processing class according to priority. Multiple custom annotations in Lombok have corresponding handler classes, as shown in the following figure:
As you can see, it is these Handler classes that actually replace, modify, and process their custom annotations in Lombok. Refer to the code for details of its implementation.
Follow wechat public account: IT elder brother
Java actual combat project video tutorial: you can get 200G, 27 sets of actual combat project video tutorial
Reply: Java learning route, you can get the latest and most complete a learning roadmap
Re: Java ebooks, get 13 must-read books for top programmers
Java foundation, Java Web, JavaEE all tutorials, including Spring Boot, etc
Reply: Resume template, you can get 100 beautiful resumes