【译】利用Lombok消除重复代码

当你在写Getter和Setter时,一定无数次的想过,为什么会有POJO这么烂的东西。你不是一个人!(不是骂人…)无数的开发人员花费了大量的时间来写这种样板代码,而他们本来可以利用这些时间做出更有价值的输出。

从我开始写Java以来,已经写了几千行代码了,其中大概50%都是样板代码,在转型之前,我就这么一直毫无怨言的写着。而最近两年,我不再Java了,转而开始写一些Python,Go和JavaScript的代码。这时我才感觉到Java中的重复的样板代码是多么令人沮丧。

值得庆幸的是,现在的IDE为我们提供了自动生成这些代码的功能。但是我仍然需要按快捷键或者点鼠标来操作,这是非常影响我的编码思路的。

Lombok简介

Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java. Never write another getter or equals method again

上面这段话摘自Lombok的首页。这是一个每个人都需要使用的库,简直是一种仙丹!开个玩笑。Java是一门很棒的语言,但是它的冗长经常会令人感到苦恼。

Lombok到底有多香呢?我总结了以下几点:

  1. Getter和Setter注解会自动生成getter、setter方法
  2. NoArgsConstructor和AllArgConstructor可以帮助你快速生成构造函数
  3. ToString会使POJO打印更加友好的日志
  4. Data会让你的POJO成为一个完全符合规范的POJO
  5. SneakyThrows可以偷偷抛出检查异常,而不需要再写throws子句

想了解更多Lombok特性的话,可以自行前往https://projectlombok.org/features/all查看。

Lombok是如何工作的?

Lombok是在Java注解处理器和几个编译时注解的帮助下工作的,它将注入额外的Java字节码来帮助我们处理重复的代码。你可以查看它生成的Java代码,这一过程被幽默的称为“Delombokisation”。

我应该如何开始使用?

Lombok引入了一个额外的编译时依赖。

如果你使用vanilla javac进行编译,你需要指定lombok.jar作为注解处理器:javac -cp lombok.jar MyCode.java

如果你使用的是maven,那么需要在pom.xml中插入以下代码来保证你的代码可以使用Lombok。

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.4</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

如果你使用的是Gradle,那么你需要使用Gradle Lombok插件

plugins {
    id 'io.franzbecker.gradle-lombok' version '1.14'
    id 'java'
}

设置你的IDE

从你开始使用Java起,你应该就开始使用一个智能的IDE来自动编译或给你的代码提供一些建议。为了将Lombok集成进IDE,你需要告诉Lombok io来安装合适的钩子。

获取Lombok的jar包后,执行java -jar lombok.jar来完成所有的设置。

IntelliJ IDEA和Visual Studio用户需要一个单独的Lombok插件,你可以选择从插件库中安装。

代码拿来!

talk is cheap, show me your code.程序员就应该拿代码说话。下面我们就来看一个完整的例子。

Getters和Setters

为被注解的自动生成getXXX和setXXX方法。

import lombok.Getter;
import lombok.Setter;

class UptimeResponse {
    // GetXXX and SetXXX are automatically generated
    @Getter @Setter private long uptime;
    @Getter @Setter private long currentTime;
    @Getter @Setter private String status;
    UptimeResponse() {
        this.uptime = ManagementFactory
                          .getRuntimeMXBean().getUptime();
        this.currentTime = System.currentTimeMillis();
        this.status = "OK";
    }
}
// So this works automagically
UptimeResponse res = new UptimeResponse();
res.setStatus("FAIL");
System.out.println(res.getUptime());

Constructors

可以自动创建默认的POJO构造函数,它将字段初始化为默认值。

  1. NoArgConstructor创建一个无参构造函数,所有的字段都会初始化为默认值
  2. AllArgsConstructor创建一个全参数构造函数,每个字段都会初始化为指定值
  3. RequiredArgsConstructor创建一个构造函数,参数包括所有final字段和标记为NotNull的字段
import lombok.*

@AllArgsConstructor
class Document {
    @Getter @Setter private String title;
    @Getter @Setter private String content;
    // ...
}
// This works automagically
Document d = new Document("Hello World", "Message Body");
d.getTitle();   // Hello World
d.getContent(); // Message Body

Equals and hash codes

Lombok可以生成的样板代码是包含局部变量的equals方法和hashcode方法。你可以手动排除一些字段。

import lombok.*;

@RequiredArgsConstructor
@EqualsAndHashCode
class User {
    @Getter
    private final String username;
    @EqualsAndHashCode.Exclude
    @Getter
    @Setter
    private String lastAction;  // not required for equality checks
}
// This works automagically
User u1 = new User("amitosh");
u1.setLastAction("Hello");
User u2 = new User("amitosh");
u2.setLastAction("Compile");
u1.equals(u2) // Gives true

To String

Lombok的ToString注解自动生成toString方法,其中包含类封装的全部字段。这是用于生成调试表示的快速方法。

import lombok.ToString;
import lombok.Getter;
import lombok.Setter;

@ToString
class Entry {
    @Getter @Setter private String id;
    @Getter @Setter private String target;
}
// This works automagically
Entry e = new Entry();
// ...
System.out.println(e);  // Nice output with values of id and target

Data classes

这个注解用于生成符合规范的完整POJO。它是ToString、EqualsAndHashCode以及所有非final字段的Getter和Setter的集合体。

import lombok.Data;

@Data
class Message {
    private String sender;
    private String content;
}
// This works automagically
Message m = new Message("amitosh", "Hello World");
m.setSender("agathver");
m.getContent();  // Hello World
m.toString();    // ...

SneakyThrows

Java是一门静态检查语言,但有时检查会比较多余。例如有时我们不关心异常,或者确定代码中不会出现异常,所以就不想去写捕获和处理异常的代码。这时SneakyThrows注解可以帮助我们一起骗过编译器。

但要注意不能滥用这个注解。

import lombok.SneakyThrows;
 
public class SneakyThrowsExample {
   @SneakyThrows(UnsupportedEncodingException.class)
   public String utf8ToString(byte[] bytes) {
       // This exception is never generated as UTF-8 is guaranteed
       // to be supported by the JVM
       return new String(bytes, "UTF-8");
   }
}

Delomboking

不是所有的工具都支持Lombok的,最著名的是JavaDoc工具。你需要有一个中间态的代码来使文档正确表示。此外,有时候你可能会想看看Lombok生成的代码到底是什么样的。幸好Lombok提供了“delomboking”,用来将Lombok转换成Java源代码。

要转换一个文件夹下的全部代码,可以使用以下命令:

java -jar lombok.jar delombok src -d src-delomboked

maven和gradle插件也包含了delomboking任务,在你需要的时候可以使用。

Lombok是一个提高你的Java生产力的工具。我无法想象没有它时应该怎么写Java程序。真心希望你在读完本文以后能够认识到它的强大!

原文地址

https://medium.com/@agathver/banish-repetitive-java-code-with-lombok-f9b97d0d4137

译者点评

Lombok是一款非常好用的工具,它可以帮助我们快速构建POJO类。但是如果直接使用@Data注解时,会破坏类的封装特性。这点不符合面向对象编程的思想,但工作中会使用一些序列化工具,这些工具要求所有字段都要有setter方法。为了编码的方便,可能使用@Data方法是一个好的选择。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,100评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,308评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,718评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,275评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,376评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,454评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,464评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,248评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,686评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,974评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,150评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,817评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,484评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,140评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,374评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,012评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,041评论 2 351

推荐阅读更多精彩内容