preface
Lombok is a handy tool that, like Google Guava, is highly recommended and should be used by every Java engineer. Lombok is a Java™ utility that helps 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 installs Lombok
-
Install via IntelliJ’s plug-in center
-
Install Plugin
-
Finally, remember to import lombok. Jar into your Project when using Lombok annotations, and add dependencies to pom.xml if you are using Maven Project.
<pre code-lang="bash" class="juejin-editor-highlight" style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, " Courier New" , monospace; The font - size: 0.8 em. position: relative; Padding: 0.5 em 1 em; background: rgb(248, 248, 248); overflow: auto; border-radius: 2px;" > < the dependency > < groupId > org. Projectlombok < / groupId > < artifactId > lombok < / artifactId > < version > 1.16.8 < / version > </dependency></pre>Copy the code
Lombok
2.1 Lombok notes
val
: used before a local variable, which is equivalent to declaring the variable final@NonNull
Adding this annotation to a method parameter automatically verifies whether the parameter is null within the method. If it is null, NullPointerException (NPE) is thrown.@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
Annotations are used simultaneously on the class@ToString
,@EqualsAndHashCode
,@Getter
,@Setter
and@RequiredArgsConstrutor
These notes, forPOJO class
It is useful to@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, it provides you with the complex Builder APIs that you can call as followsPerson.builder().name("Adam Savage").city("San Francisco").job("Mythbusters").job("Unchained Reaction").build();
For more informationBuilder@SneakyThrows
: Automatically throws checked exceptions without explicitly using throws statements on methods@Synchronized
: used on a method to declare the method synchronous and automatically lock the lock object, which is a private property$lock
or$LOCK
Locking on this or its own class has the side effect that you cannot prevent uncontrolled code from locking this or its own class, which can 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);
2.2 Lombok code examples
- Val sample
<pre code-lang="bash" class="juejin-editor-highlight" style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, " Courier New" , monospace; The font - size: 0.8 em. position: relative; Padding: 0.5 em 1 em; background: rgb(248, 248, 248); overflow: auto; border-radius: 2px;" >public static void main(String[] args) { val sets = new HashSet<String>(); val lists = new ArrayList<String>(); val maps = new HashMap<String, String>(); Final Set<String> sets2 = new HashSet<>(); final List<String> lists2 = new ArrayList<>(); final Map<String, String> maps2 = new HashMap<>(); } </pre>Copy the code
- @ NonNull sample
<pre code-lang="bash" class="juejin-editor-highlight" style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, " Courier New" , monospace; The font - size: 0.8 em. position: relative; Padding: 0.5 em 1 em; background: rgb(248, 248, 248); overflow: auto; border-radius: 2px;" >public void notNullExample(@NonNull String string) { string.length(); } public void notNullExample(String String) {if (String! = null) { string.length(); } else { throw new NullPointerException("null"); } } </pre>Copy the code
- @ the Cleanup examples
<pre code-lang="bash" class="juejin-editor-highlight" style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, " Courier New" , monospace; The font - size: 0.8 em. position: relative; Padding: 0.5 em 1 em; background: rgb(248, 248, 248); overflow: auto; border-radius: 2px;" >public static void main(String[] args) { try { @Cleanup InputStream inputStream = new FileInputStream(args[0]); } catch (FileNotFoundException e) { e.printStackTrace(); } InputStream InputStream = null; try { inputStream = new FileInputStream(args[0]); } catch (FileNotFoundException e) { e.printStackTrace(); } finally { if (inputStream ! = null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } </pre>Copy the code
- @ Getter / @ Setter example
<pre code-lang="bash" class="juejin-editor-highlight" style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, " Courier New" , monospace; The font - size: 0.8 em. position: relative; Padding: 0.5 em 1 em; background: rgb(248, 248, 248); overflow: auto; border-radius: 2px;" >@Setter(AccessLevel.PUBLIC) @Getter(AccessLevel.PROTECTED) private int id; private String shap; </pre>Copy the code
- @ ToString sample
<pre code-lang="bash" class="juejin-editor-highlight" style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, " Courier New" , monospace; The font - size: 0.8 em. position: relative; Padding: 0.5 em 1 em; background: rgb(248, 248, 248); overflow: auto; border-radius: 2px;" >@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(new LombokDemo()); } } </pre>Copy the code
- @ EqualsAndHashCode sample
<pre code-lang="bash" class="juejin-editor-highlight" style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, " Courier New" , monospace; The font - size: 0.8 em. position: relative; Padding: 0.5 em 1 em; background: rgb(248, 248, 248); overflow: auto; border-radius: 2px;" >@EqualsAndHashCode(exclude = {"id", "shape"}, callSuper = false) public class LombokDemo { private int id; private String shap; } </pre>Copy the code
- NoArgsConstructor, @requiredargsconstructor and @allargsconstructor examples
<pre code-lang="bash" class="juejin-editor-highlight" style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, " Courier New" , monospace; The font - size: 0.8 em. position: relative; Padding: 0.5 em 1 em; background: rgb(248, 248, 248); overflow: auto; border-radius: 2px;" >@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"); // Construct new LombokDemo() with no arguments; New LombokDemo(1, "circle", 2); } } </pre>Copy the code
- @ the Data sample
<pre code-lang="bash" class="juejin-editor-highlight" style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, " Courier New" , monospace; The font - size: 0.8 em. position: relative; Padding: 0.5 em 1 em; background: rgb(248, 248, 248); overflow: auto; border-radius: 2px;" >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; Private float thresHold = 0; // newThresHold private float newThresHold = 0; // private float totalScore = 0; } </pre>Copy the code
- @ the Value sample
<pre code-lang="bash" class="juejin-editor-highlight" style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, " Courier New" , monospace; The font - size: 0.8 em. position: relative; Padding: 0.5 em 1 em; background: rgb(248, 248, 248); overflow: auto; border-radius: 2px;" >@Value public class LombokDemo { @NonNull private int id; @NonNull private String shap; private int age; Private final int id; public int getId() { return this.id; }... } </pre>Copy the code
- @ Builder sample
<pre code-lang="bash" class="juejin-editor-highlight" style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, " Courier New" , monospace; The font - size: 0.8 em. position: relative; Padding: 0.5 em 1 em; background: rgb(248, 248, 248); overflow: auto; border-radius: 2px;" >@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(); } } </pre>Copy the code
- @ SneakyThrows sample
<pre code-lang="bash" class="juejin-editor-highlight" style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, " Courier New" , monospace; The font - size: 0.8 em. position: relative; Padding: 0.5 em 1 em; background: rgb(248, 248, 248); overflow: auto; border-radius: 2px;" >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(); Public void read() throws FileNotFoundException {InputStream InputStream = new FileInputStream(""); } public void write() throws UnsupportedEncodingException { throw new UnsupportedEncodingException(); } } </pre>Copy the code
- @ Synchronized sample
<pre code-lang="bash" class="juejin-editor-highlight" style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, " Courier New" , monospace; The font - size: 0.8 em. position: relative; Padding: 0.5 em 1 em; background: rgb(248, 248, 248); overflow: auto; border-radius: 2px;" >public class SynchronizedDemo { @Synchronized public static void hello() { System.out.println("world"); } private static final Object $LOCK = new Object[0]; public static void hello() { synchronized ($LOCK) { System.out.println("world"); } } } </pre>Copy the code
- @Getter(lazy = true)
<pre code-lang="bash" class="juejin-editor-highlight" style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, " Courier New" , monospace; The font - size: 0.8 em. position: relative; Padding: 0.5 em 1 em; background: rgb(248, 248, 248); overflow: auto; border-radius: 2px;" >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); } return result; }}Copy the code
// 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);
}
return result;
}
}</pre>
Copy the code
Lombok annotations
Speaking of Lombok, we have to mention JSR 269: Pluggable Annotation Processing API. We had annotations before JSR 269, but we had to use reflection to do something, and reflection was very limited. First, it must define @retention as retentionpolicy.runtime, which can only get annotation values at RUNTIME through reflection, making run-time code inefficient. Second, if you want to use annotations to do some checking at compile time, and to report errors to the user for some unreasonable code, reflection doesn’t work. After JSR 269 we can use annotations to do this at compile time in Javac. So we find that the core differentiates between run time and compile time.
As you can see from the figure above, Annotation Processing is a step between parsing and generation. The detailed steps are as follows:
The diagram above shows Lombok’s process. After the Javac has been parsed into an abstract syntax tree (AST), Lombok dynamically modiates the AST, adding new nodes (called code), and eventually parsing and generating bytecode, based on its own annotation processor.
Since Java 6, Javac has supported the “JSR 269 Pluggable Annotation Processing API” specification, which can be called whenever a program implements the API while Javac is running.
- The Java compiler used by Maven, a popular project management tool, is configured with a third-party tool. If you configure the third-party tool as Oracle Javac, then Maven supports Lombok directly.
- If Intellij Idea is configured using Oracle Javac, lombok is directly supported.
IDE tool problem solving:
You now have A class A with some fields that use Lombok’s @data annotation without the setter and getter methods for creating them, and A class B that calls the setter and getter methods for the corresponding fields of class A instances
Compiling projects in class A and class B does not generate an error because the resulting class A bytecode file has setter and getter methods for the corresponding fields
However, the IDE finds that setter and getter methods for class A instances used in class B source code are not defined in class A source code, and the IDE considers this an error
To resolve the above error, which is not a true error, download and install the “Lombok Plugin “in Intellij Idea.
4. Customize annotations to support JSR269
In the general compilation process of JavAC, Java files are first parsed to build an AST, followed by annotation processing, and finally analyzed and optimized to generate binary.class files. What we can do is do some processing in the annotation processing phase. First we create the following files under meta-inf. services:
Documents specified in the annotation processor: com. Alipay. Kris. Other. Lombok. MyAnnotaionProcessor, then we meet you can write your own annotations processor, a simple example code is as follows:
<pre code-lang="bash" class="juejin-editor-highlight" style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, " Courier New" , monospace; The font - size: 0.8 em. position: relative; Padding: 0.5 em 1 em; background: rgb(248, 248, 248); overflow: auto; border-radius: 2px;" >@SupportedSourceVersion(SourceVersion.RELEASE_8) @SupportedAnnotationTypes("com.alipay.kris.other.lombok.*") public class MyAnnotaionProcessor extends AbstractProcessor { public MyAnnotaionProcessor() { super(); } @Override public boolean process(Set<? extends TypeElement> annotations,RoundEnvironment roundEnv) { for (Element elem : roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) { MyAnnotation annotation = elem.getAnnotation(MyAnnotation.class); String message = "annotation found in " + elem.getSimpleName() + " with " + annotation.value(); addToString(elem); processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, message); } return true; // no further processing of this annotation type } }</pre>Copy the code
That’s the end of the article
Like xiaobian to share technical articles can like attention oh!
There are also some Java core information collection and 2020Java interview information summary
Public account: Kylin bug