项目 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 + "]";
}
}
A class should have getter-setters for the instance variables, equals
& hashCode
method implementation, all field constructors and an implementation of toString
method. This class so far has no business logic and even without it is 80+ lines of code. This is insane.
项目 Lombok
项目 Lombok 是一个 Java 库,可以自动集成到您的编辑器和构建工具中,并帮助减少样板代码。让我们首先看看如何设置 Lombok 项目。
Java 项目 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。这是基于为实例变量firstName设置的Lombok的@Getter
和@Setter
注解。
在Java字节码中查看Lombok的外观
我们可以检查来自类字节码的getter和setter方法的添加。
项目Lombok注解
项目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生成带有所有参数的构造函数
- 通过@NonNull在构造函数中传递参数时进行空值检查。在将参数作为方法的参数传递时,也可以使用@NonNull注解
以下是程序运行的结果。
@RequiredArgsConstructor
会为每个需要特殊处理的字段生成一个参数的构造函数。所有未初始化的最终字段都会获得一个参数,以及任何被标记为@NonNull
但在声明时未初始化的字段。 -
Getter/Setter注解
这些注解可以在字段或类级别使用。如果需要精细控制,则在字段级别使用。当在类级别使用时,将创建所有的getter/setter。让我们在上面创建的类上进行操作。
@AllArgsConstructor @Getter @Setter public class PersonLombok { String firstName; String lastName; LocalDate dateOfBirth; }
-
equals, hashCode 和 toString 注解
我们在创建类时通常建议覆盖
hashCode()
和equals()
方法。在Lombok中,我们有@EqualsAndHashCode
注解,它会注入equals() & hashCode()方法的代码,因为它们通常是一起使用的。此外,@ToString
注解提供了toString()方法的实现。让我们来看看:@AllArgsConstructor @Getter @Setter @EqualsAndHashCode @ToString public class PersonLombok { String firstName; String lastName; LocalDate dateOfBirth; }
现在,我们已经只用Lombok注解就实现了Person类的创建,而不需要任何样板代码。然而,这还可以进一步优化,我们可以用
@Data
注解替换上面类中的所有注解,得到相同的功能。 -
基于设计模式的注解
@Builder
允许您自动生成代码,使您的类可以使用构建器模式进行实例化。@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
生成委托方法,将调用转发到使用该注解的字段上。”偏爱组合而非继承“,但这会创建大量类似于适配器模式的样板代码。 Lombok 在实现此功能时参考了 Groovy 同名注解。让我们看一个实现:@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("在 Adaptee.display() 中"); } }
Lombok为所有注解提供了细粒度控制的功能。
样板代码:Java架构师在听吗?
是的,它们确实如此。你需要明白,与其他语言不同,Java 已经非常小心地升级了语言,以确保不破坏任何旧版本 Java 中存在的代码库。这本身就是一项巨大的任务,不能被低估。他们已经在语言中修改并构建了更好的类型推断能力。Java 10 计划中的一个重要特性是局部变量类型推断。虽然这个特性更多地涉及到添加动态类型而不是样板文件,但这只是管理样板代码中的一小部分。
总结
减少样板代码有助于提高可读性,更少的代码也意味着更少的错误。Project Lombok 今天在几乎所有主要组织中都得到了广泛使用。我们为你提供了 Lombok 中最有用的功能。希望你尝试一下。源代码:你可以访问我的Github 链接下载本教程中使用的完整源代码。
Source:
https://www.digitalocean.com/community/tutorials/java-project-lombok