• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
思想人生从关注生活开始
博客园    首页    新随笔    联系   管理    订阅  订阅

Java 中的不可变对象-Java快速进阶教程

1. 概述

在本教程中,我们将学习是什么使对象不可变,如何在 Java 中实现不可变性,以及这样做有什么好处。

2. 什么是不可变对象?

不可变对象是其内部状态在完全创建后保持不变的对象。

这意味着不可变对象的公共 API 保证了它在其整个生命周期中的行为方式相同。

如果我们看一下类 String,我们可以看到,即使它的 API 似乎通过其replace方法为我们提供了可变行为,原始字符串也不会改变:

String name = "testjack";
String newName = name.replace("jack", "----");

assertEquals("testjack", name);
assertEquals("test----", newName);

API 为我们提供了只读方法,它绝不应包含更改对象内部状态的方法。

3. Java中的final 关键字

在尝试在 Java 中实现不变性之前,我们应该讨论final关键字。

在 Java 中,变量默认是可变的,这意味着我们可以更改它们保存的值。

通过在声明变量时使用final关键字,Java 编译器不允许我们更改该变量的值。相反,它将报告编译时错误:

final String name = "baeldung";
name = "bael...";

请注意,final仅禁止我们更改变量持有的引用,它不会保护我们使用其公共 API 更改它引用的对象的内部状态:

final List<String> strings = new ArrayList<>();
assertEquals(0, strings.size());
strings.add("testjack");
assertEquals(0, strings.size());

第二个assertEquals将失败,因为将元素添加到列表中会更改其大小,因此,它不是一个不可变的对象。

4. Java中的不可变性

现在我们知道了如何避免更改变量的内容,我们可以使用它来构建不可变对象的 API。

构建不可变对象的 API 需要我们保证无论我们如何使用其 API 都不会更改其内部状态。

朝着正确方向前进的一步是在声明其属性时使用final:

class Money {
    private final double amount;
    private final Currency currency;

    // ...
}

请注意,Java保证了金额的值不会改变,所有基元类型变量都是如此。

但是,在我们的示例中,我们只能保证货币不会更改,因此我们必须依靠货币API 来保护自身免受更改。

大多数时候,我们需要对象的属性来保存自定义值,而初始化不可变对象的内部状态的地方是它的构造函数:

class Money {
    // ...
    public Money(double amount, Currency currency) {
        this.amount = amount;
        this.currency = currency;
    }

    public Currency getCurrency() {
        return currency;
    }

    public double getAmount() {
        return amount;
    }
}

正如我们之前所说,为了满足不可变 API 的要求,我们的Money类只有只读方法。

使用反射 API,我们可以打破不可变性并更改不可变对象。但是,反射违反了不可变对象的公共 API,通常,我们应该避免这样做。

5. 好处

由于不可变对象的内部状态在时间上保持不变,因此我们可以在多个线程之间安全地共享它。

我们也可以自由使用它,引用它的对象都不会注意到任何差异,我们可以说不可变的对象没有副作用。

6. 结论

不可变对象不会及时更改其内部状态,它们是线程安全的,并且没有副作用。由于这些属性,不可变对象在处理多线程环境时也特别有用。

posted @ 2023-02-22 12:56  JackYang  阅读(279)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3