java 中不可变对象

java 不可变对象

本文我们说明什么是不可变对象,在java 中如何实现以及其有和好处。

1. 什么是不可变对象

不可变对象是指对象被创建之后,其内部状态保存不变的对象。这意味着其公开的API保证在对象的整个生命周期中其行为保持一致。

下面我们看看String类,即使我们使用其replace api提供了一个可变的行为,但其原字符串并没有改变:

String name = "baeldung";
String newName = name.replace("dung", "----");
 
assertEquals("baeldung", name);
assertEquals("bael----", newName);

该API属于只读方法,String中没有改变其内部状态的方法.

2. final 关键字

在我们实现不可变之前,我们先讨论下final关键字。在java中,变量默认是可变的,意味着我们可以修改其值。通过使用final关键字声明对象,java编译器不会让我们改变变量的值,否则会报错:

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

需要注意的是,final仅禁止我们改变变量的引用,但不阻止通过公开API改变对象的内部状态:

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

第二个assertEquals 会失败,因为增加元素值list会改变其size,因此,其非不可变对象。

3. java 中不可变性

现在我们知道如何避免改变变量的内容,因此可以构建不可变对象的API。其目的是无论我们如何使用其API,都需要保证对象内部状态不变。

正确的做法是使用final关键字声明对象属性:

class Money {
    private final double amount;
    private final Currency currency;
 
    // ...
}

java保证我们amount值不会改变,因为其为基本类型变量。然而上述代码仅会保证currency不会改变,因此我们必须依赖Currency 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,通常我们应该避免这样。

4. 优势

因为不可变对象内部状态始终保持不变,我们可以多线程中安全地共享使用。我们也可以自由地使用它,引用它的任何对象都不会有任何区别,因此不可变对象是无副作用的。

5. 总结

不可变对象任何时候不会修改其内部状态,是线程安全的,可以无副作用使用。因此,不可变对象在处理多线程环境下特别有用。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值