lombok和maven_Lombok,AutoValue和Immutables,或如何编写更少,更好的代码返回

lombok和maven

在上一篇有关Lombok库的文章中 ,我描述了一个库,该库有助于处理Java中的样板代码( 是的,我知道这些问题已经在Kotlin中解决了 ,但这是现实生活,我们不能一味地坐下来,一旦出现较新或更简单的语言,请重写每个现有项目。 但是生活中有很多事情, Lombok项目有其替代方案。 让我们也给他们一个机会。

本文的代码示例可在此处和此处找到。

它实际上是Lombok的替代方案-因为您不能一次使用两者。 或者,至少事实证明,在同一个项目中同时使用IntelliJ IDEA和IntelliJ IDEA时,您将遇到很多困难,因为这是许多人真正选择的IDE,因为这两个库处理批注处理的方式不同。 因此,两个人都无法生存,而另一个人则得以幸存,这大约是哈利·波特和伏地魔的预言所表达的方式 。

因此,我们已经知道使用Lombok批注的Person类的外观

@Builder(toBuilder = true)
@ToString
@EqualsAndHashCode
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class Person {@NonNull@Getterprivate final String lastName;@NonNull@Getterprivate final String firstName;@NonNull@Getterprivate final Integer age;
}

如果我们创建一个新项目并按此处所述使用autovalue ,则可以使用AutoValue Builders模仿几乎相同的模型 。

现在让我们看一下AutoValue模型的外观:

package autovalue.model;import com.google.auto.value.AutoValue;@AutoValue
public abstract class Person {public abstract String lastName();public abstract String firstName();public abstract Integer age();public static Person create(String lastName, String firstName, Integer age) {return builder().lastName(lastName).firstName(firstName).age(age).build();}public static Builder builder() {return new AutoValue_Person.Builder();}@AutoValue.Builderpublic abstract static class Builder {public abstract Builder lastName(String lastName);public abstract Builder firstName(String firstName);public abstract Builder age(Integer age);public abstract Person build();}
}

您可以看到的是, 肯定有更多的代码

Lombok生成带有单个注释的构建器时, AutoValue将使您创建自己的构建器代码-尽管不是全部。 基本上,您定义接口后,实现将由AutoValue生成的代码完成,您不必实际实现getter和setter中的代码。 即使我们同意AutoValue getter接口不会比Lombok字段定义花费更多的时间或空间,但是对于某些人来说,编写AutoValue构建器代码仍然是一件麻烦事。

但是,它可以提供更大的灵活性 ,因为您实际上可以更改构建器方法名称。 此外, 代码分析和使用情况搜索是一个巨大的胜利–这样,您实际上可以分别查找实际的getter和setter的用法,这对开发人员也可能很重要。

实例的创建方法与Lombok相同。

final Person anna = Person.builder().age(31).firstName("Anna").lastName("Smith").build();

我们所有的测试都在代码更改最少的情况下运行,主要是因为AutoValue无法将实例转换为构建器(或者至少我不容易找到它),因此复制只是调用静态工厂方法:

package autovalue.model;import org.junit.Test;import static org.assertj.core.api.Java6Assertions.assertThat;public class PersonTest {private static Person JOHN = Person.builder().firstName("John").lastName("Doe").age(30).build();private static Person JANE = Person.builder().firstName("Jane").lastName("Doe").age(30).build();@Testpublic void testEquals() throws Exception {Person JOHN_COPY = Person.create(JOHN.lastName(), JOHN.firstName(), JOHN.age());assertThat(JOHN_COPY).isEqualTo(JOHN);}@Testpublic void testNotEquals() throws Exception {assertThat(JANE).isNotEqualTo(JOHN);}@Testpublic void testHashCode() throws Exception {Person JOHN_COPY = Person.create(JOHN.lastName(), JOHN.firstName(), JOHN.age());assertThat(JOHN_COPY.hashCode()).isEqualTo(JOHN.hashCode());}@Testpublic void testHashCodeNotEquals() throws Exception {Person JOHN_COPY = Person.create(JOHN.lastName(), JOHN.firstName(), JOHN.age());assertThat(JOHN_COPY.hashCode()).isNotEqualTo(JANE.hashCode());}@Testpublic void testToString() throws Exception {String jane = JANE.toString();assertThat(jane).contains(JANE.lastName());assertThat(jane).contains(JANE.firstName());assertThat(jane).contains("" + JANE.age());assertThat(jane).doesNotContain(JOHN.firstName());}}

其他显而易见的区别:

  • 您编写的AutoValue类始终是抽象的。 它们在AutoValue生成的代码中实现。
  • AutoValue类是自动不可变的。 有一种解决方法,使它们具有不可变类型的属性 。 即使您明确希望在实例上具有setter, 也不能 。

为什么要使用AutoValueAutoValue的创建者会谨慎地在此处描述该库的收益,甚至就此创建一个完整的演示文稿 。

该库还使用Java注释处理器来生成简单,安全和一致的值对象。 好吧,与前两个相同。 还有什么是新的? 让我们来看看。

最简单的值类如下所示。

package immutables.model;import org.immutables.value.Value;@Value.Immutable
public abstract class Person {public abstract String lastName();public abstract String firstName();public abstract Integer age();
}

因此,具有抽象类的相同原理仅在生成的代码中实现。 为此,您需要启用IDE注释处理器 ,就像对Lombok一样 (但对于AutoValue则不需要,因为它是由gradle插件完成的)。

那么,对象创建的外观如何?

final Person anna = ImmutablePerson.builder().age(31).firstName("Anna").lastName("Smith").build();
System.out.println(anna);

乍一看,最明显的区别是:

  • 我们不声明构建器方法。
  • 静态的builder / factory方法不是在我们自己的类上创建的,而是在生成的类上创建的。
  • 与AutoValue一样,无法在类上生成生成器,只能在生成器上生成。
  • 生成的类也自动 -ers,就是实例方法,允许通过改变一个属性来创建实例的副本补充说:
final ImmutablePerson anna = ImmutablePerson.builder().age(31).firstName("Anna").lastName("Smith").build();
System.out.println(anna);final ImmutablePerson annaTheSecond = anna.withAge(23).withLastName("Smurf");
System.out.println(annaTheSecond);
  • 该构建器具有自动添加的from()方法,该方法允许创建实例的精确副本,并且在生成的类上还有一个生成的静态copyOf()方法:
Person JOHN_COPY = ImmutablePerson.builder().from(JOHN).build();
// OR
Person JOHN_COPY = ImmutablePerson.copyOf(JOHN);

同样,我们的测试运行时所做的更改很小,主要是关于如何复制实例的:

package immutables.model;import org.junit.Test;import static org.assertj.core.api.Assertions.assertThat;public class PersonTest {private static Person JOHN = ImmutablePerson.builder().firstName("John").lastName("Doe").age(30).build();private static Person JANE = ImmutablePerson.builder().firstName("Jane").lastName("Doe").age(30).build();@Testpublic void testEquals() throws Exception {//ImmutablePerson JOHN_COPY = ImmutablePerson.builder().from(JOHN).build();Person JOHN_COPY = ImmutablePerson.copyOf(JOHN);assertThat(JOHN_COPY).isEqualTo(JOHN);}@Testpublic void testNotEquals() throws Exception {assertThat(JANE).isNotEqualTo(JOHN);}@Testpublic void testHashCode() throws Exception {Person JOHN_COPY = ImmutablePerson.copyOf(JOHN);assertThat(JOHN_COPY.hashCode()).isEqualTo(JOHN.hashCode());}@Testpublic void testHashCodeNotEquals() throws Exception {Person JOHN_COPY = ImmutablePerson.copyOf(JOHN);assertThat(JOHN_COPY.hashCode()).isNotEqualTo(JANE.hashCode());}@Testpublic void testToString() throws Exception {String jane = JANE.toString();assertThat(jane).contains(JANE.firstName());assertThat(jane).contains(JANE.lastName());assertThat(jane).contains("" + JANE.age());assertThat(jane).doesNotContain(JOHN.firstName());}}

关于Immutables库,还有很多要说的,因此这里有一本相当大的手册 。 在本文中,我们仅对表面进行了一些刮擦。 例如,有关使用Immitables和样式自定义 (方法前缀,构建器名称等)以及甚至为Mongo生成存储库以便将文档视为不可变对象的 JSON序列化的更多细节。 但是,这比我在这篇简单文章中所涉及的要多得多。

要解决的问题是,尚未普及的Java语言的挑战之一就是冗长和样板代码。 但是有很多工具可以处理它,并且可以选择最合适的库,而不是通过复制粘贴或尝试编写自己的代码生成器进行编码。

好好利用它们。

好好用

翻译自: https://www.javacodegeeks.com/2018/03/lombok-autovalue-and-immutables-or-how-to-write-less-and-better-code-returns.html

lombok和maven

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/333704.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

上传文件显示进度条_文件上传带进度条进阶-断点续传

说明 1. 把文件按大小1M分割成N份 2. 每次上传时,告诉后台大文件的md5、当前第几份(从0开始)、总共几份 3. 并行上传,前端同时开启5个请求进行传输增加速度 4. 上传失败或出错后,继续上传下一份,把出错的份…

Unix 下的 vim 如何使用系统剪贴板

在 Unix 环境下," 寄存器需要 xterm-clipboard feature 的 VIM 软件才能使用,具有这个 feature 的 VIM 可以安装 vim-gtk(包含gvim和vim),使用 gvim 可以正常调用 " 寄存器。

python中关键字global的简单理解

python用global关键字来标识函数里或类里的全局变量,下面以例子来看看global关键字的作用。 未使用global关键字 a10 #全局变量 def sum(x):a2 #局部变量xa*xreturn x xsum(3) print("a:",a) #10 输出的是全局变量a10 print("x:",x) #6使用…

apache kafka_2018年机器学习趋势与Apache Kafka生态系统相结合

apache kafka在慕尼黑举行的OOP 2018大会上,我介绍了有关使用Apache Kafka生态系统和诸如TensorFlow,DeepLearning4J或H2O之类的深度学习框架构建可扩展,关键任务微服务的演讲的更新版本。 我想分享更新后的幻灯片,并讨论一些有关…

cookies丢失 同域名_后端设置Cookie前端跨域获取丢失问题(基于springboot实现)

1.跨域问题说明:后端域名为A.abc.com,前端域名为B.abc.com。2.后端设置一个cookie发送给前台,domain应该是setDomain(“abc.com”),而不是setDomain(“B.abc.com”)3.另外,还要实现WebMvcConfigurerr配置加入Cors的跨域…

shell脚本--使用for循环逐行访问txt文件

方法1 export text_pathdata/1.txt for line in $(cat $text_path) doecho $line done方法2 export text_pathdata/1.txt for line in cat $text_path doecho $line done

vertx rest 跨域_Vertx编程风格:您的React式Web Companion REST API解释了

vertx rest 跨域Vertx提供了许多在轻量级环境中进行编程的选项,例如node.js。 但是,对于新用户来说,选择采用哪种方法来创建REST API几乎不会造成混淆。 在vertx中进行编程时,可以采用不同的模型。 下面通过易于理解的图表进行说…

输出节点位移_绝对值信号的编码器有哪些信号输出(一、二)

绝对值信号的编码器有哪些信号输出(一、二)之前介绍过很多次拉线位移传感器输出是有两大类的,数字信号输出和模拟量信号输出,而数字信号输出还分为增量型脉冲信号输出和绝对值信号输出,今天就系统的介绍一下绝对值信号…

vim 中的 quickfix 指令

用 quickfix 可以快速修改编译错误。 运行了 make 命令编译之后,如果有编译错误 Vim 会以列表形式把编译错误列出,并使用 quickfix 工具快速帮你定位出错的行。 指令说明cc显示编译错误的详细信息,这些信息显示在状态行里cn下一个编译错误cp前一个编译…

Python第三方库的安装,升级以及版本查看

方法:通过电脑的cmd命令行来进行python第三方库的安装,升级以及版本查看 安装和升级pip 安装pip方法1 在cmd命令行输入以下命令: python -m ensurepip #当提示不存在pip时使用这行代码进行安装安装pip方法2 在终端输入以下命令&#xf…

混合多云架构_混合多云每个人都应避免的3个陷阱(第1部分)

混合多云架构每天都在肆意宣传云,但每个人都应避免三个陷阱。 从云,混合云到混合多云,您都被告知这是确保业务数字化未来的一种方式。 您必须做出的这些选择不会排除提高客户体验和敏捷交付这些应用程序的日常工作。 让我们开始一段旅程&am…

vim 下的 ex 指令(底行命令模式下)

文章目录 (一)复制(二)文档光标移动(三)删除(四)粘贴(五)保存/退出(六)另存为文件/选取内容另存文件(七)查找/搜索字符(八)搜索指令 vimgrep(九)使用搜索指令 grep(十)文本行移动(十一)匹配模式替换(十二)显示行号(十三)normal 命令(十四)文件信息…

datastax.repo_使用Datastax Java驱动程序与Cassandra进行交互

datastax.repo今天,我这次返回了更多的Cassandra和Java集成,重点是使用Datastax Java驱动程序,而不是我已经写了很多文章的Spring Data Cassandra。 Spring Data实际上使用了Datastax驱动程序来与Cassandra进行交互,但是在它之上还…

beanshell断言_JMeter使用BeanShell断言

BeanShell简介BeanShell是使用Java语法的一套脚本语言,在JMeter的多种组件中都有BeanShell的身影,如:定时器:BeanShell Timer前置处理器:BeanShell PreProcessor采样器:BeanShell Sampler后置处理器&#x…

Mobaxterm常用的指令(基于linux)

列出所有的环境(3种方法) conda env list conda info --envs conda info -e创建虚拟环境(默认anaconda3/envs路径) conda create -n megumi python3.8.5 #megumi为环境名称,#3.8.5是安装python的版本激活环境(2种方法) source activate 环境名 conda activate 环境名退出环…

junit mockito_使用JUnit 5在Mockito中方便地进行模拟–官方方式

junit mockito从版本2.17.0开始,如果使用了JUnit 5, Mockito提供了官方(内置)支持来管理模拟生命周期。 入门 为了利用集成的优势,需要在JUnit 5的junit-platform-engine旁边添加Mockito的mockito-junit-jupiter依赖项…

正则表达式中的量词(限定符)含义的准确理解

量词准确理解?前面的元素(pattern/子表达式)匹配 0 次或者 1 次;出现 0 次或者 1 次。“次”改成“个”也行*前面的元素匹配大于等于 0 个前面的元素匹配大于等于 1 个{5}前面的元素匹配 5 个{2,6}前面的元素匹配 2 个到 6 个

docker初识_初识 docker 搭建自己的开发环境

换了一台设备,程序猿嘛第一件事肯定是先把开发环境搭建起来,以前为了方便都是搞的集成环境,这次准备下载集成环境的时候,突然想起 docker 这个东西,在下虽然了解一些概念性的东西但一直为曾实践。人嘛,没有…

PyTorch中使用指定的GPU

PyTorch默认使用从0开始的GPU,如果GPU0正在运行程序,需要指定其他GPU。 有如下两种方法来指定需要使用的GPU。 1.类似tensorflow指定GPU的方式,使用CUDA_VISIBLE_DEVICES。 1.1 直接终端中设定: CUDA_VISIBLE_DEVICES1 python…

jvm运行时类加载机制_JVM体系结构:JVM类加载器和运行时数据区

jvm运行时类加载机制各位读者好! 在JVM系列的上一篇文章中,开发人员了解了Java虚拟机(JVM)及其体系结构。 本教程将帮助开发人员正确回答以下主题的问题: ClassLoader子系统 运行时数据区 1.简介 在继续之前&#x…