Immutables 简介

评论 0 浏览 0 2016-08-01

一、简介

在本文中,我们将展示如何使用 Immutables 库。

该库由注释和注释处理器组成,用于生成和使用可序列化和可定制的不可变对象。

2.Maven依赖

为了在项目中使用 Immutables,您需要将以下依赖项添加到 pom.xml 文件的 dependencies 部分:

<dependency>
    <groupId>org.immutables</groupId>
    <artifactId>value</artifactId>
    <version>2.2.10</version>
    <scope>provided</scope>
</dependency>

由于运行时不需要此工件,因此建议指定提供范围。

可以在此处找到该库的最新版本。

3. Immutables

该库从抽象类型生成不可变对象:接口注释

实现这一点的关键是正确使用 @Value.Immutable 注解。 它生成带注释类型的不可变版本,并在其名称前加上 Immutable 关键字

如果我们尝试生成名为“X”的类的不可变版本,它将生成一个名为“ImmutableX”的类。生成的类不是递归不变的,因此最好记住这一点。

快速说明一下 - 因为 Immutables 使用注释处理,所以您需要记住在 IDE 中启用注释处理。

3.1.将@Value.Immutable抽象类接口结合使用

让我们创建一个简单的abstractPerson,由两个abstract访问器方法组成,代表要生成的字段,然后用@Value.Immutable 注释:

@Value.Immutable
public abstract class Person {

    abstract String getName();
    abstract Integer getAge();

}

注解处理完成后,我们可以在 target/generated-sources 目录中找到一个新生成的 ImmutablePerson

@Generated({"Immutables.generator", "Person"})
public final class ImmutablePerson extends Person {

    private final String name;
    private final Integer age;

    private ImmutablePerson(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    String getName() {
        return name;
    }

    @Override
    Integer getAge() {
        return age;
    }

    // toString, hashcode, equals, copyOf and Builder omitted

}

生成的类附带已实现的 toString、hashcode、equals 方法和 Stepbuilder ImmutablePerson.Builder。请注意,生成的构造函数具有私有访问权限。

为了构造 ImmutablePerson 类的实例,我们需要使用构建器或静态方法 ImmutablePerson.copyOf,它可以从Person 对象创建一个 ImmutablePerson 副本。

如果我们想使用构建器构造一个实例,我们可以简单地编写代码:

ImmutablePerson john = ImmutablePerson.builder()
  .age(42)
  .name("John")
  .build();

生成的类是不可变的,这意味着它们不能被修改。如果要修改已存在的对象,可以使用“withX”方法之一,该方法不会修改原始对象,而是使用修改后的字段创建一个新实例。

让我们更新john的年龄并创建一个新的john43对象:

ImmutablePerson john43 = john.withAge(43);

在这种情况下,以下断言将成立:

assertThat(john).isNotSameAs(john43);
assertThat(john.getAge()).isEqualTo(42);

4. 附加实用程序

如果不能定制的话,这样的类生成就不会很有用。 Immutables 库附带了一组附加注释,可用于自定义 @Value.Immutable 的输出。要查看所有这些内容,请参阅 Immutables 的文档

4.1. @Value.Parameter 注解

@Value.Parameter注解可用于指定应生成构造方法的字段。

如果你像这样注释你的类:

@Value.Immutable
public abstract class Person {

    @Value.Parameter
    abstract String getName();

    @Value.Parameter
    abstract Integer getAge();
}

可以通过以下方式实例化它:

ImmutablePerson.of("John", 42);

4.2. @Value.Default 注解

@Value.Default 注释允许您指定在未提供初始值时应使用的默认值。为此,您需要创建一个返回固定值的非抽象访问器方法,并使用 @Value.Default 对其进行注释:

@Value.Immutable
public abstract class Person {

    abstract String getName();

    @Value.Default
    Integer getAge() {
        return 42;
    }
}

以下断言将成立:

ImmutablePerson john = ImmutablePerson.builder()
  .name("John")
  .build();

assertThat(john.getAge()).isEqualTo(42);

4.3. @Value.Auxiliary 注解

@Value.Auxiliary 注释可用于注释将存储在对象实例中的属性,但会被 equalshashCodetoString 忽略该属性。

如果你像这样注释你的类:

@Value.Immutable
public abstract class Person {

    abstract String getName();
    abstract Integer getAge();

    @Value.Auxiliary
    abstract String getAuxiliaryField();

}

使用辅助字段时,以下断言为真:

ImmutablePerson john1 = ImmutablePerson.builder()
  .name("John")
  .age(42)
  .auxiliaryField("Value1")
  .build();

ImmutablePerson john2 = ImmutablePerson.builder()
  .name("John")
  .age(42)
  .auxiliaryField("Value2")
  .build();

assertThat(john1.equals(john2)).isTrue();
assertThat(john1.toString()).isEqualTo(john2.toString());
assertThat(john1.hashCode()).isEqualTo(john2.hashCode());

4.4. @Value.Immutable(Prehash = True) 注解

由于我们生成的类是不可变的并且永远无法修改,因此 hashCode 结果将始终保持不变,并且在对象实例化期间只能计算一次。

如果你像这样注释你的类:

@Value.Immutable(prehash = true)
public abstract class Person {

    abstract String getName();
    abstract Integer getAge();

}

检查生成的类时,您可以看到 hashcode 值现在已预先计算并存储在字段中:

@Generated({"Immutables.generator", "Person"})
public final class ImmutablePerson extends Person {

    private final String name;
    private final Integer age;
    private final int hashCode;

    private ImmutablePerson(String name, Integer age) {
        this.name = name;
        this.age = age;
        this.hashCode = computeHashCode();
    }

    // generated methods
 
    @Override
    public int hashCode() {
        return hashCode;
    }
}

hashCode() 方法返回构造对象时生成的预先计算的哈希码

5. 结论

在本快速教程中,我们展示了 Immutables 库的基本工作原理。

文章中的所有源代码和单元测试都可以在 GitHub 代码库 中找到。

最后更新2023-11-08
0 个评论
标签