Java 项目 Lombok
Project Lombok 是帮助 Java 项目减少样板代码的一个非常有用的工具。
问题陈述
在 Java 与其他语言的争论中,其他语言支持者给你的第一个批评是 Java 需要大量的样板代码,你无法克服它,你毫无防备。多个平台和开发者社区也报告了同样的问题。让我们看一个包含样板代码的代码示例。
package com.askrakesh.java.manage_boilerplate;
import java.time.LocalDate;
public class Person {
String firstName;
String lastName;
LocalDate dateOfBirth;
public Person(String firstName, String lastName, LocalDate dateOfBirth) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.dateOfBirth = dateOfBirth;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public LocalDate getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(LocalDate dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((dateOfBirth == null) ? 0 : dateOfBirth.hashCode());
result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (dateOfBirth == null) {
if (other.dateOfBirth != null)
return false;
} else if (!dateOfBirth.equals(other.dateOfBirth))
return false;
if (firstName == null) {
if (other.firstName != null)
return false;
} else if (!firstName.equals(other.firstName))
return false;
if (lastName == null) {
if (other.lastName != null)
return false;
} else if (!lastName.equals(other.lastName))
return false;
return true;
}
@Override
public String toString() {
return "Person [firstName=" + firstName + ", lastName=" + lastName + "dateOfBirth=" + dateOfBirth + "]";
}
}
类应该具有实例变量的 getter-setter、equals
方法hashCode
实现、所有字段构造函数和方法实现toString
。这个类到目前为止还没有业务逻辑,即使没有业务逻辑,也有 80 多行代码。这太疯狂了。
龙目岛计划
Project Lombok 是一个 Java 库,可自动插入编辑器和构建工具,并有助于减少样板代码。让我们先看看如何设置 Lombok 项目。
Java Project Lombok 如何工作?
Lombok 有各种注释,可以在我们的代码中使用,这些注释将在编译时进行处理,并根据所使用的注释进行适当的代码扩展。Lombok 仅在查看时进行代码缩减,在编译字节码后注入所有样板。这有助于保持我们的代码库小巧、干净、易于阅读和维护。
Lombok 项目 Maven
在您的项目中添加 Lombok 很简单。只需在您的 maven 项目 pom.xml 文件中添加以下依赖项即可。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
</dependency>
在 IDE(Eclipse)中添加 Lombok 插件
以下是 Windows 的安装步骤:
- 从https://projectlombok.org/download下载 jar或使用从 maven 构建下载的 jar。
- 在终端中执行命令:
java -jar lombok.jar
- 该命令将打开如下图所示的窗口,安装并退出安装程序并重新启动 eclipse。
如果您使用的是 MacOS,那么以下是在项目中使用 Lombok 的步骤。
- 将 lombok.jar 复制到
Eclipse.app/Contents/MacOS
目录中。 - 添加
-javaagent:lombok.jar
到文件末尾Eclipse.app/Contents/Eclipse/eclipse.ini
。 - 重新启动 Eclipse 并在项目属性中启用“注释处理”,如下图所示。
Eclipse 轮廓中的 Lombok 一瞥
安装后,让我们检查一下如何查看简化的样板代码?我重新创建了与 相同的类PersonLombok
。Eclipse 大纲显示了 firstName 的 getter 和 setter。这是基于 Lombok 的@Getter
&@Setter
注释集(实例变量 firstName)完成的。
Lombok 窥探 Java 字节码
我们可以从类字节码中检查 firstName 的 getter 和 setter 方法的添加。
Project Lombok 注释
Project Lombok 提供了很多注释,有助于减少各种场景中的样板代码。让我们来看看其中的几个。
-
构造函数注解
@AllArgsConstructor public class PersonLombok { @NonNull String firstName; String lastName; LocalDate dateOfBirth; public static void main(String[] args) { new PersonLombok(null, "Kumar", LocalDate.now()); } }
上面的代码在类中注入了以下内容:
- 通过@AllArgsConstructor获得所有参数的构造函数
- 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
Here’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()"); } }
Lombok provides functionality for fine grained control in all the annotations.
Boiler-Plate: Are Java Architects Listening?
Yes, they are. You need to understand unlike other languages, Java has taken utmost care of upgrading the language such that they do not break any existing codebase which are in older versions of java. This itself is a huge task and cannot be undermined. They are already modifying and building better type inference capabilities in the language which has been rolled out. One of the important features planned for Java 10 is Local-Variable Type Inference. Though the feature has more to do with adding dynamic typing than the boiler plate, but it is a small drop in the Ocean to manage the boiler-plate code.
Summary
减少样板代码有助于提高可读性,更少的代码也意味着更少的错误。Lombok 项目如今在几乎所有主要组织中都得到了广泛使用。我们为您提供了 Lombok 中最有用的功能。希望您尝试一下。源代码:您可以访问我的Github 链接下载本教程中使用的完整源代码。