Java 项目 Lombok

项目 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的安装步骤:

  1. https://projectlombok.org/download下载jar文件,或使用从maven构建下载的jar文件。
  2. 在终端执行以下命令:java -jar lombok.jar
  3. 此命令将打开如下图所示的窗口,请安装并退出安装程序,然后重新启动eclipse。

如果您使用的是 MacOS,则以下是在项目中使用 Lombok 的步骤。

  1. 将lombok.jar复制到Eclipse.app/Contents/MacOS目录中。
  2. -javaagent:lombok.jar添加到Eclipse.app/Contents/Eclipse/eclipse.ini文件的末尾。
  3. 重新启动Eclipse,并在项目属性中启用“注解处理”,如下图所示。

在Eclipse大纲中查看Lombok的外观

安装后,让我们检查如何查看我们的减少的样板代码?我已经重新创建了与PersonLombok相同的类。Eclipse大纲显示了firstName的getter和setter。这是基于为实例变量firstName设置的Lombok的@Getter@Setter 注解

在Java字节码中查看Lombok的外观

我们可以检查来自类字节码的getter和setter方法的添加。

项目Lombok注解

项目Lombok提供了许多注解,可以帮助在各种场景中减少样板代码。让我们来看看其中一些。

  1. 构造函数注解

    @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但在声明时未初始化的字段。

  2. Getter/Setter注解

    这些注解可以在字段或类级别使用。如果需要精细控制,则在字段级别使用。当在类级别使用时,将创建所有的getter/setter。让我们在上面创建的类上进行操作。

    @AllArgsConstructor @Getter @Setter
    public class PersonLombok {
    	String firstName;
    	String lastName;
    	LocalDate dateOfBirth;
    }
    
  3. 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注解替换上面类中的所有注解,得到相同的功能。

  4. 基于设计模式的注解

    @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