【翻译八】final字段的值会变?

How can final fields appear to change their values?

One of the best examples of how final fields' values can be seen to change involves one particular implementation of the String class.

这里通过一个String类的实例,看看final字段的值是如何看起来改变的。

A String can be implemented as an object with three fields -- a character array, an offset into that array, and a length. The rationale for implementing String this way, instead of having only the character array, is that it lets multiple String and StringBuffer objects share the same character array and avoid additional object allocation and copying. So, for example, the method String.substring() can be implemented by creating a new string which shares the same character array with the original String and merely differs in the length and offset fields. For a String, these fields are all final fields.

String类的实例对象有三个字段,一个字符数组array,数组中的偏移量offset,还有一个长度length。之所以用array + offset + length ,而不是一个array,来实现一个String,是这样可以使多个String和StringBuffer对象共享相同的array,并且避免额外的对象分配和拷贝。例如,String.subString()创建的子串String对象,它和原String共享一个array,仅有的不同之处是offset和length不一样。对于一个String来说,这些字段都是final的。

    String s1 = "/usr/tmp";
    String s2 = s1.substring(4); 

The string s2 will have an offset of 4 and a length of 4. But, under the old model, it was possible for another thread to see the offset as having the default value of 0, and then later see the correct value of 4, it will appear as if the string "/usr" changes to "/tmp".

对于以上代码,s2的offset是4,length是4,但在旧的内存模型下,其他线程可能看到的offset是默认的0,过会才会看到是4,因为final字段在构造过程中就泄露了出去。这样引发的血案就是,s2刚开始是"/usr"然后变成了"/tmp"。此处贴出源码如下。

    public String substring(int beginIndex) {
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        int subLen = value.length - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        //value就是那个final character array
        return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
    }

The original Java Memory Model allowed this behavior; several JVMs have exhibited this behavior. The new Java Memory Model makes this illegal.

最初的JMM允许这样的血案,也会发生在一些JVM中。但新内存模型已经禁止了这种行为。

转载于:https://my.oschina.net/u/3035165/blog/865897

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值