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字段的值是如何看起來改變的。app
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.this
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".code
對於以上代碼,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.three
最初的JMM容許這樣的血案,也會發生在一些JVM中。但新內存模型已經禁止了這種行爲。ip