原标题:Lombok 要知道的 8 个点

关注:“锅外的大佬”

专注分享国外最新技术内容

帮助每位开发者更优秀地成长

和其他语言相比, Java经常因为不必要的冗长被批评。 Lombok提供了一系列注解用以在后台生成模板代码,将其从你的类中删除,从而有助于保持你的代码整洁。较少的模板意味着更简洁的代码,更易于阅读和维护。在本文中,我将涉及我经常使用的 Lombok功能,并想你展示如何使用他们生产更清晰、更简洁的代码。

1.局部变量类型推断:val 和 var

许多语言通过查看等号右侧的表达式来推断局部变量类型。尽管现在 Java10+已经支持这种功能,但在之前的版本中没有 Lombok的帮助就无法实现。下面的代码段展示了如何显式指定局部类型:

final Map map = new HashMap<>;

map.put("Joe", 21);

在 Lombok中,我们可以通过使用 val来缩短它,如下所示:

val valMap = new HashMap;

valMap.put("Sam", 30);

注意, val在背后创建了一个 final且不可变的变量。如果你需要一个可变本地变量,可以使用 var。

2.@NonNull

对方法参数进行 null检查通常不是一个坏主意,特别是如果该方法形成的 API被其他开发者使用。虽然这些检查很简单,但是他们可能变得冗长,特别是当你有多个参数时。如下所示,额外的代码无助于可读性,并且可能从方法的主要目的分散注意力。

public void nonNullDemo(Employee employee, Account account) {

if(employee == null) {

throw new IllegalArgumentException("Employee is marked @NonNull but is null");

}

if(account == null) {

throw new IllegalArgumentException("Account is marked @NonNull but is null");

}

// do stuff

}

理想情况下,你需要 null检查——没有干扰的那种。这就是 @NonNull发挥作用的地方。通过用 @NonNull标记参数, Lombok替你为该参数生成 null检查。你的方法突然变得更加简洁,但没有丢失那些安全性的 null检查。

public void nonNullDemo(@NonNull Employee employee, @NonNull Account account) {

// just do stuff

}

默认情况下, Lombok会抛出 NullPointerException,如果你愿意,可以配置 Lombok抛出 IllegalArgumentException。我个人更喜欢 IllegalArgumentException,因为我认为它更适合于对参数检查。

3.更简洁的数据类

数据类是 Lombok真正有助于减少模板代码的领域。在查看该选项前,思考一下我们经常需要处理的模板种类。数据类通常包括以下一种或全部:

构造函数(有或没有参数)

私有成员变量的 getter 方法

私有非 final 成员变量的 setter 方法

帮助记录日志的 toString 方法

equals 和 hashCode(处理相等/集合)

可以通过 IDE 生成以上内容,因此问题不在于编写他们花费的时间。问题是带有少量成员变量的简单类很快会变得非常冗长。让我们看看 Lombok如何通过处理上述的每一项来减少混乱。

3.1. @Getter 和 @Setter

想想下面的 Car类。当生成 getter和 setter时,我们会得到接近 50 行代码来描述一个包含 5 个成员变量的类。

public class Car {

private String make;

private String model;

private String bodyType;

private int yearOfManufacture;

private int cubicCapacity;

public String getMake {

return make;

}

public void setMake(String make) {

this.make = make;

}

public String getModel {

return model;

}

public void setModel(String model) {

this.model = model;

}

public String getBodyType {

return bodyType;

}

public void setBodyType(String bodyType) {

this.bodyType = bodyType;

}

public int getYearOfManufacture {

return yearOfManufacture;

}

public void setYearOfManufacture(int yearOfManufacture) {

this.yearOfManufacture = yearOfManufacture;

}

public int getCubicCapacity {

return cubicCapacity;

}

public void setCubicCapacity(int cubicCapacity) {

this.cubicCapacity = cubicCapacity;

}

}

Lombok可以替你生成 getter和 setter模板。通过对每个成员变量使用 @Getter和 @Setter注解,你最终得到一个等效的类,如下所示:

public class Car {

@Getter @Setter

private String make;

@Getter @Setter

private String model;

@Getter @Setter

private String bodyType;

@Getter @Setter

private int yearOfManufacture;

@Getter @Setter

private int cubicCapacity;

}

注意,你可以在非 final成员变量上只使用 @Setter。在 final成员变量上使用它将导致编译错误。

如果你需要为每个成员变量生成 getter和 setter,你也可以在类级别使用 @Getter和 @Setter,如下所示。

@Getter

@Setter

public class Car {

private String make;

private String model;

private String bodyType;

private int yearOfManufacture;

private int cubicCapacity;

}3.2. @AllArgsConstructor

数据类通常包含一个构造函数,它为每个成员变量接受参数。IDE 为 Car生成的构造函数如下所示:

public class Car {

@Getter @Setter

private String make;

@Getter @Setter

private String model;

@Getter @Setter

private String bodyType;

@Getter @Setter

private int yearOfManufacture;

@Getter @Setter

private int cubicCapacity;

public Car(String make, String model, String bodyType, int yearOfManufacture, int cubicCapacity) {

super;

this.make = make;

this.model = model;

this.bodyType = bodyType;

this.yearOfManufacture = yearOfManufacture;

this.cubicCapacity = cubicCapacity;

}

}

我们可以使用 @AllArgsConstructor注解实现同样功能。 @Getter和 @Setter、 @AllArgsConstructor减少模板,保持类更干净且更简洁。

@AllArgsConstructor

public class Car {

@Getter @Setter

private String make;

@Getter @Setter

private String model;

@Getter @Setter

private String bodyType;

@Getter @Setter

private int yearOfManufacture;

@Getter @Setter

private int cubicCapacity;

}

还有其他选项用于生成构造函数。 @RequiredArgsConstructor将创建带有每个 final成员变量参数的构造函数, @NoArgsConstructor将创建没有参数的构造函数。

3.3. @ToString

在你的数据类上覆盖 toString方法是有助于记录日志的良好实践。IDE 为 Car类生成的 toString方法如下所示:

@AllArgsConstructor

public class Car {

@Getter @Setter

private String make;

@Getter @Setter

private String model;

@Getter @Setter

private String bodyType;

@Getter @Setter

private int yearOfManufacture;

@Getter @Setter

private int cubicCapacity;

@Override

public String toString {

return "Car [make=" + make + ", model=" + model + ", bodyType=" + bodyType + ", yearOfManufacture="

+ yearOfManufacture + ", cubicCapacity=" + cubicCapacity + "]";

}

}

我们可以使用 ToString注解废除这个,如下所示:

@ToString

@AllArgsConstructor

public class Car {

@Getter @Setter

private String make;

@Getter @Setter

private String model;

@Getter @Setter

private String bodyType;

@Getter @Setter

private int yearOfManufacture;

@Getter @Setter

private int cubicCapacity;

}

默认情况下, Lombok生成包含所有成员变量的 toString方法。可以通过 exclude属性 @ToString(exclude={"someField"},"someOtherField"})覆盖行为将某些成员变量排除。

3.4. @EqualsAndHashCode

如果你正在将你的数据类和任何类型的对象比较,则需要覆盖 equals和 hashCode方法。对象的相等是基于业务规则定义的。举个例子,在 Car类中,如果两个对象有相同的 make、 model和 bodyType,我可能认为他们是相等的。如果我使用 IDE 生成 equals方法检查 make、 model和 bodyType,它看起来会是这样:

@Override

public boolean equals(Object obj) {

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass != obj.getClass)

return false;

Car other = (Car) obj;

if (bodyType == null) {

if (other.bodyType != null)

return false;

} else if (!bodyType.equals(other.bodyType))

return false;

if (make == null) {

if (other.make != null)

return false;

} else if (!make.equals(other.make))

return false;

if (model == null) {

if (other.model != null)

return false;

} else if (!model.equals(other.model))

return false;

return true;

}

等价的 hashCode实现如下所示:

@Override

public int hashCode {

final int prime = 31;

int result = 1;

result = prime * result + ((bodyType == null) ? 0 : bodyType.hashCode);

result = prime * result + ((make == null) ? 0 : make.hashCode);

result = prime * result + ((model == null) ? 0 : model.hashCode);

return result;

}

虽然 IDE 处理了繁重的工作,但我们在类中仍然有大量的模板代码。 Lombok允许我们使用 @EqualsAndHashCode类注解实现相同的功能,如下所示:

@ToString

@AllArgsConstructor

@EqualsAndHashCode(exclude = { "yearOfManufacture", "cubicCapacity" })

public class Car {

@Getter @Setter

private String make;

@Getter @Setter

private String model;

@Getter @Setter

private String bodyType;

@Getter @Setter

private int yearOfManufacture;

@Getter @Setter

private int cubicCapacity;

}

默认情况下, @EqualsAndHashCode会创建包含所有成员变量的 equals和 hashCode方法。 exclude选项可用于通知 Lombok排除某些成员变量。在上面的代码片段中。我已经从生成的 equals和 hashCode方法中排除了 yearOfManuFacture和 cubicCapacity。

3.5. @Data

如果你想使数据类尽可能精简,可以使用 @Data注解。 @Data是 @Getter、 @Setter、 @ToString、 @EqualsAndHashCode和 @RequiredArgsConstructor的快捷方式。

@ToString

@RequiredArgsConstructor

@EqualsAndHashCode(exclude = { "yearOfManufacture", "cubicCapacity" })

public class Car {

@Getter @Setter

private String make;

@Getter @Setter

private String model;

@Getter @Setter

private String bodyType;

@Getter @Setter

private int yearOfManufacture;

@Getter @Setter

private int cubicCapacity;

}

通过使用 @Data,我们可以将上面的类精简如下:

@Data

public class Car {

private String make;

private String model;

private String bodyType;

private int yearOfManufacture;

private int cubicCapacity;

}4. 使用 @Buidler 创建对象

建造者设计模式描述了一种灵活的创建对象的方式。 Lombok可以帮你轻松的实现该模式。看一个使用简单 Car类的示例。假设我们希望可以创建各种 Car对象,但我们希望在创建时设置的属性具有灵活性。

@AllArgsConstructor

public class Car {

private String make;

private String model;

private String bodyType;

private int yearOfManufacture;

private int cubicCapacity;

private List serviceDate;

}

假设我们要创建一个 Car,但只想设置 make和 model。在 Car上使用标准的全参数构造函数意味着我们只提供 make和 model并设置其他参数为 null。

Car2 car2 = new Car2("Ford", "Mustang", null, null, null, null);

这可行但并不理想,我们必须为我们不感兴趣的参数传递 null。我们可以创建一个只接受 make和 model的构造函数来避开这个问题。这是一个合理的解决方法,但不够灵活。如果我们有许多不同的字段排列,我们可以用什么来创建一个新 Car?最终我们得到了一堆不同的构造函数,代表了我们可以实例化 Car的所有可能方式。

解决该问题的一种干净、灵活的方式是使用建造者模式。 Lombok通过 @Builder注解帮你实现建造者模式。当你使用 @Builder注解 Car类时, Lombok会执行以下操作:

添加一个私有构造函数到 Car

创建一个静态的 CarBuilder类

在 CarBuilder中为 Car中的每个成员创建一个 setter风格方法。

在 CarBuilder中添加创建 Car的新实例的建造方法。

CarBuilder上的每个 setter风格方法返回自身的实例( CarBuilder)。这允许你进行方法链式调用并为对象创建提供流畅的 API。让我们看看它如何使用。

Car muscleCar = Car.builder.make("Ford")

.model("mustang")

.bodyType("coupe")

.build;

现在只使用 make和 model创建 Car比之前更简洁了。只需在 Car上简单的调用生成的 builder方法获取 CarBuilder实例,然后调用任何我们感兴趣的 setter风格方法。最后,调用 build创建 Car的新实例。

另一个值得一提的方便的注解是 @Singular。默认情况下,Lombok 为集合创建使用集合参数的标准的 setter风格方法。在下面的例子中,我们创建了新的 Car并设置了服务日期列表。

Car muscleCar = Car.builder.make("Ford")

.model("mustang")

.serviceDate(Arrays.asList(LocalDate.of(2016, 5, 4)))

.build;

向集合成员变量添加 @Singular将提供一个额外的方法,允许你向集合添加单个项。

@Builder

public class Car {

private String make;

private String model;

private String bodyType;

private int yearOfManufacture;

private int cubicCapacity;

@Singular

private List serviceDate;

}

现在我们可以添加单个服务日期,如下所示:

Car muscleCar3 = Car.builder

.make("Ford")

.model("mustang")

.serviceDate(LocalDate.of(2016, 5, 4))

.build;

这是一个有助于在创建对象期间处理集合时保持代码简洁的快捷方法。

5.日志

Lombok另一个伟大的功能是日志记录器。如果没有 Lombok,要实例化标准的 SLF4J日志记录器,通常会有以下内容:

public class SomeService {

private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);

public void doStuff{

log.debug("doing stuff....");

}

}

这些日志记录器很沉重,并为每个需要日志记录的类添加了不必要的混乱。值得庆幸的是 Lombok提供了一个为你创建日志记录器的注解。你要做的所有事情就是在类上添加注解,这样就可以了。

@Slf4j

public class SomeService {

public void doStuff{

log.debug("doing stuff....");

}

}

我在这里使用了 @SLF4J注解,但 Lombok能为几乎所有通用 Java日志框架生成日志记录器。有关更多日志记录器的选项,请参阅文档。

6.Lombok给你控制权

我非常喜欢 Lombok的一点是它的不侵入性。。如果你决定在使用如 @Getter、 @Setter或 @ToString时也想要自己的方法实现,你的方法将总是优先于 Lombok。它允许你在大多数时间使用 Lombok,但在你需要的时候仍有控制权。

7.写得更少,做得更多

在过去的 4 到 5 年里,我几乎在每个项目中都使用了 Lombok。我喜欢它,因为它减少了杂乱,最终得到了更干净、更简洁、更易阅读的代码。它不一定为你节省大量时间,因为它生成的代码可以由 IDE 自动生成。话虽如此,我认为更干净的代码的好处不仅仅是将其添加到 Java堆栈中。

8. 延展阅读

我已经介绍了我经常使用的 Lombok功能,但还有很多我没有讲到。如果你喜欢目前为止所看到的,并希望了解更多,请继续阅读 Lombok 文档。

原文链接:https://dzone.com/articles/introduction-to-lombok

作者:Brian Hannaway

译者:Darren Luo

上篇好文:

点击在看,和我一起帮助更多开发者!返回搜狐,查看更多

责任编辑:

lombok null字段不显示 继承_Lombok 要知道的 8 个点相关推荐

  1. 字段不显示 继承_Springboot Shiro页面按钮显示、路径越权访问题

    阅读前文章 SpringBoot Shiro 实现登录/记住我的功能 SpringBoot Shiro基于Url权限拦截系统 本文导读 通过以上两篇文章,已经实现了shiro登录,基于Url实现权限拦 ...

  2. kubectl logs -f tail 显示100_系统管理员应该知道的9个kubectl命令

    kubectl是Kubernetes的一个命令行管理工具,可用于Kubernetes上的应用部署和日常管理.本文列举了9个常见的kubectl命令,并对每个命令进行了简单扼要的介绍,供大家参考.同时, ...

  3. surface6桌面显示计算机,你所应该知道的Surface快捷键全攻略

    导言:作为微软在Windows8桌面操作系统和WindowsPhone手机操作系统之外.介于桌面和手持设备之间的又一力作,Surface的出现给我们带来了很多惊喜.但是在使用过程中有哪些容易被忽略的使 ...

  4. java oracle 图片_JAVA读取Oracle中的blob图片字段并显示

    JAVA读取Oracle中的blob图片字段并显示 近期,在给客户做一个Demo页面时,需要用JAVA读取Oracle中的blob图片字段并显示,在此过程中,遇到一些问题,例如:连接Oracle数据库 ...

  5. mysql vba日期空值_使用SQL(VBA/ADO)命令填充来自重复记录的相应非空值的NULL字段...

    我有一个数据库,其中有数百个记录已被复制.但是,重复的信息在所有字段中都不相同.对于任何两行,第一行将包含一些字段中的信息,而重复行的字段为空;但对于其他字段,重复(第二)行将包含信息,而第一行的字段 ...

  6. 返回json格式 不忽略null字段

    返回json格式 不忽略null字段 发布于 353天前  作者 king666  271 次浏览  复制  上一个帖子  下一个帖子  标签: json 如题,一个实体的某个字段如果为null,在转 ...

  7. JAVA读取Oracle中的blob图片字段并显示

    转自:http://www.blogjava.net/zhangqingping/articles/JAVA.html 近期,在给客户做一个Demo页面时,需要用JAVA读取Oracle中的blob图 ...

  8. 工具方法:一次性将对象中所有null字段,转为空字符串

    当我们的 Java 对象在响应前端,或者在做数据导出的时候,我们并不希望将对象中为 null 的属性值直接返回给前端,不然显示或导出的就是一个 null ,这样对用户不是很友好. 如果我们一个个字段的 ...

  9. 将日志中的指定字段对齐显示输出

    在分析ats的访问日志时,我经常会遇到将一些特殊字段对齐显示的需求,网上调研了一下,发现使用column -t就可以轻松搞定,比如 找到ATS的access.log中的200响应时间过长的日志 cat ...

最新文章

  1. 支付宝AI摘下视觉竞赛世界冠军,能精准区分同种类物体的细微差别
  2. 数据中心运营商如何选择合适的蓄电池
  3. 具备安全态势感知能力的安全管理平台
  4. sql union 与多个order by 一起使用
  5. YBTOJ洛谷P4551:最长异或路径(trie树)
  6. thinkjs——两表联查
  7. 消息(4)——WS附件传输,包体中的base64编码附件
  8. 使用JAVA文件上传的几种方式
  9. pc模式 华为mate30_很实用!华为Mate 30全系支持PC模式,无线充+投屏更方便!
  10. 免费网课python_Python网课推荐——免费学习Python编程
  11. python删除第一行_python学习之删除DataFrame某一行/列内容
  12. 升级Ubuntu造成RTL8125网卡驱动丢失
  13. 中职计算机公开课说课稿,(完整)中职职高幼教专业手工实践《剪纸(雪花)》公开课说课稿...
  14. java环信后端接口
  15. 计算机怎么联网络,电脑怎么连接网络
  16. 云渲染那个好?云渲染测评终极章。市面上在的都在了!
  17. 码云与与GitHUB的对比及使用码云使用细节
  18. 视频加速播放插件-Global Speed
  19. Tomcat官网地址
  20. 嵌入式数据库SQLite

热门文章

  1. 腾讯云数据库2020年度盛典等你来
  2. 走进5G | 腾讯技术工程5G技术沙龙开启报名啦!
  3. ORC文件存储格式的深入探究
  4. leetcode 482. 密钥格式化(Java版)
  5. leetcode 257. 二叉树的所有路径(Java版)
  6. JVM详解之:java class文件的密码本
  7. java中final的意义
  8. 洛谷——P1177 【模板】快速排序
  9. hdu 1565 方格取数(1)
  10. 满分最优解法:1007 素数对猜想 (20分)