Project Lombok 是 Java 项目减少锅炉板代码的一个非常有用的工具。
问题声明
In Java vs. other language debate, the first knock which you get from other language supporters is that Java requires lot of boiler plate code and you just cannot get over it, and you are defenceless. The same issue is also reported in multiple platforms and developer communities. Let’s see a sample of code which has boiler plate code.
1package com.askrakesh.java.manage_boilerplate;
2
3import java.time.LocalDate;
4
5public class Person {
6
7 String firstName;
8 String lastName;
9 LocalDate dateOfBirth;
10
11 public Person(String firstName, String lastName, LocalDate dateOfBirth) {
12 super();
13 this.firstName = firstName;
14 this.lastName = lastName;
15 this.dateOfBirth = dateOfBirth;
16 }
17
18 public String getFirstName() {
19 return firstName;
20 }
21
22 public void setFirstName(String firstName) {
23 this.firstName = firstName;
24 }
25
26 public String getLastName() {
27 return lastName;
28 }
29
30 public void setLastName(String lastName) {
31 this.lastName = lastName;
32 }
33
34 public LocalDate getDateOfBirth() {
35 return dateOfBirth;
36 }
37
38 public void setDateOfBirth(LocalDate dateOfBirth) {
39 this.dateOfBirth = dateOfBirth;
40 }
41
42 @Override
43 public int hashCode() {
44 final int prime = 31;
45 int result = 1;
46 result = prime * result + ((dateOfBirth == null) ? 0 : dateOfBirth.hashCode());
47 result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
48 result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
49 return result;
50 }
51
52 @Override
53 public boolean equals(Object obj) {
54 if (this == obj)
55 return true;
56 if (obj == null)
57 return false;
58 if (getClass() != obj.getClass())
59 return false;
60 Person other = (Person) obj;
61 if (dateOfBirth == null) {
62 if (other.dateOfBirth != null)
63 return false;
64 } else if (!dateOfBirth.equals(other.dateOfBirth))
65 return false;
66 if (firstName == null) {
67 if (other.firstName != null)
68 return false;
69 } else if (!firstName.equals(other.firstName))
70 return false;
71 if (lastName == null) {
72 if (other.lastName != null)
73 return false;
74 } else if (!lastName.equals(other.lastName))
75 return false;
76 return true;
77 }
78
79 @Override
80 public String toString() {
81 return "Person [firstName=" + firstName + ", lastName=" + lastName + "dateOfBirth=" + dateOfBirth + "]";
82 }
83
84}
一个类应该为实例变量,‘equals’和‘hashCode’方法实现,所有字段构造器和一个toString
方法实现而设定。
项目Lombok
Project Lombok 是一个 Java 库,自动插入您的编辑器和构建工具,并有助于减少锅炉板代码。
Java Lombok 是如何工作的?
Lombok有各种注释,可以在我们的代码中使用,在编译时间内进行处理,并根据使用的注释进行适当的代码扩展。 Lombok仅在编译后将字节代码注入所有锅炉板后进行代码减少,这有助于保持我们的代码库小,干净,易于阅读和维护。
项目Lombok Maven
将 Lombok 添加到您的项目很简单,只需在您的 maven 项目 pom.xml 文件中添加下面的依赖性。
1<dependency>
2 <groupId>org.projectlombok</groupId>
3 <artifactId>lombok</artifactId>
4 <version>1.16.20</version>
5</dependency>
在 IDE 中添加 Lombok 插件(Eclipse)
以下是Windows的安装步骤:
- 從 [https://projectlombok.org/download]下載 jar(https://projectlombok.org/download)或使用從你的maven build下載 jar
- 在終端執行命令:
java -jar lombok.jar
- 這個命令會開啟如下圖中所示的窗口,安裝並離開安裝程式並重新啟動 eclipse
If you are on MacOS, then following are the steps to use Lombok in your project.
- Copy lombok.jar into
Eclipse.app/Contents/MacOS
directory. - Add
-javaagent:lombok.jar
to the end ofEclipse.app/Contents/Eclipse/eclipse.ini
file. - Restart Eclipse and enable "Annotation Processing" in project properties as shown in below image.
伦博克在Eclipse的概述
After installation let’s check how we can see our reduced boiler plate code? I have recreated the same class as PersonLombok
. Eclipse outline which displays getter and setter for firstName. This was done based on the Lombok’s @Getter
& @Setter
annotation set for instance variable firstName.
在 Java 字节代码中使用 Lombok’s peek
We can check the addition of getter & setter methods for the firstName from class bytecode.
项目Lombok评论
Project Lombok提供了许多注释,这有助于在各种情况下减少锅炉板代码。
Constructor Annotation
1@AllArgsConstructor 2public class PersonLombok { 3 @NonNull String firstName; 4 String lastName; 5 LocalDate dateOfBirth; 6 public static void main(String[] args) { 7 new PersonLombok(null, "Kumar", LocalDate.now()); 8 } 9} 10```Above code injects the following in the class:- A constructor with all arguments by @AllArgsConstructor 11- Null check during when passing an argument in the Constructor by @NonNull. @NonNull annotation can also be used when passing an argument as a parameter to a method 12Here’s the result of the program run.  `@RequiredArgsConstructor` generates a constructor with 1 parameter for each field that requires special handling. All non-initialized final fields get a parameter, as well as any fields that are marked as `@NonNull` that aren't initialized where they are declared.
Getter/Setter Annotations
These annotations can be used either at the field or class level. If you want fine grained control then use it at field level. When used at class level all the getter/setters are created. Let’s work on the class we had created above.``` @AllArgsConstructor @Getter @Setter public class PersonLombok { String firstName; String lastName; LocalDate dateOfBirth; }
equals, hashCode and toString annotations
It's recommended to override the
hashCode()
andequals()
methods while creating a class. In Lombok we have@EqualsAndHashCode
annotation which injects code for equals() & hashCode() method as they go together. Additionally a@ToString
annotation provides a toString() implementation. Let’s see this:@AllArgsConstructor @Getter @Setter @EqualsAndHashCode @ToString public class PersonLombok { String firstName; String lastName; LocalDate dateOfBirth; }
We now have achieved to create Person class without any boiler plate code with help of Lombok annotations. However it gets even better we can replace all the annotations used in the above class with@Data
and get the same functionality.Design Pattern based Annotations
@Builder
lets you automatically produce the code required to have your class be instantiable using builder pattern.``` @Builder public class Employee { String firstName; String lastName; LocalDate dateOfBirth;public static void main(String[] args) { Employee emp = new EmployeeBuilder().firstName("Rakesh") .lastName("Kumar") .dateOfBirth(LocalDate.now()) .build(); }
} ````@Delegate` generates delegate methods that forward the call to this field on which annotation is used. "Favour Composition over Inheritance", but this creates a lot of boiler plate code similar to Adapter Pattern. Lombok’s took the clue from Groovy’s annotation by the same name while implementing this functionality. Let’s see an implementation:``` @RequiredArgsConstructor public class AdapterImpl implements Adapter { @Delegate private final Adaptee instance;
public static void main(String[] args) { AdapterImpl impl = new AdapterImpl(new Adaptee()); impl.display(); }
}
interface Adapter { public void display(); }
class Adaptee { public void display() { System.out.println("In Adaptee.display()"); } }
Boiler-Plate: Java 架构师在倾听吗?
是的,他们是。你需要理解,与其他语言不同,Java已经尽最大努力升级该语言,以便它们不会破坏任何现有的代码库,这些都存在于Java的较旧版本中。这本身是一个巨大的任务,不能被破坏。他们已经在修改和构建更好的类型推断能力,在已经部署的语言中。Java 10计划的重要功能之一是 Local-Variable Type Inference。尽管该功能与增加动态打字比锅炉板有关,但它是管理锅炉板代码的海洋中的一小滴。
摘要
减少锅炉板代码有助于更好的可读性,更少的代码也意味着更少的错误。Lombok项目今天在几乎所有主要组织中都广泛使用。我们为您提供了Lombok最有用的功能。希望您尝试一下。 源代码:您可以访问我的Github链接(https://github.com/askrakesh/examples/tree/master/blog-posts/manage-boilerplate)来下载本教程中使用的完整源代码。