java 不变性条件,Java中的不变性

If my class is going to be an immutable one it has to be final and without any method that modifies its state and all properties must be private. But why should it have properties declared as final (for example, private final int a)?

Edit

Will the class still be an immutable one if it has a reference to objects that are not immutable?

解决方案

From Jeremy Manson's blog post Immutability in Java:

Now, in common parlance, immutability

means "does not change". Immutability

doesn't mean "does not change" in

Java. It means "is transitively

reachable from a final field, has not

changed since the final field was set,

and a reference to the object

containing the final field did not

escape the constructor".

Manson co-authored the Java Memory Model spec, so should be knowing what he is talking about.

An example from the Brian Goetz's Java Concurrency in Practice book:

public Holder holder;

public void initialize() { holder = new Holder(42); }

publc class Holder {

private int n;

public Holder(int n) { this.n = n; }

public void assertSanity() {

if (n != n) {

throw new AssertionError(”This statement is false”);

}

}

}

// Thread 1: // Thread 2:

initialize(); if (holder != null) holder.assertSanity();

Thread 2 above can throw the AssertionError. To avoid such visibility issues the field n of Holder class should have been declared final.

EDIT: Consider the sequence of steps:

Allocate memory for new object of type Holder

Initialize field n of the new object

Execute the constructor

Assign the reference of the new object to holder reference

This is the "sane" sequence of events and the JMM (Java Memory Model) guarantees that this is what the thread calling initialize() will see. But, since there is no synchronization, JMM makes no guarantees about what sequence the second thread calling holder.assertSanity() will see. In particular, the AssertionError will be thrown if the second thread sees the sequence:

holder is non-null, so that it could call assertSanity method

The first read of n results in 0, the default value of an int field

The second read of n results 42

In short, when an object's constructor returns in one thread, another thread might not see all field initializations of that object. To guarantee that the second thread sees the correctly initialized fields, you should either make them final, or do a mutex unlock (i.e. initialize() method should be synchronized) or do a volatile write (i.e. holder should be volatile).

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值