Final字段如何改變它們的值

我們可以通過分析String類的實現(xiàn)具體細(xì)節(jié)來展示一個final變量是如何可以改變的缩功。

String 對象包含了三個字段: 一個character數(shù)組值骇,一個數(shù)組的offset和一個length。實現(xiàn)String類的基本原理為:它不僅僅擁有character數(shù)組吠卷,而且為了避免多余的對象分配和拷貝鳄哭,多個String和StringBuffer對象都會共享相同的character數(shù)組泰佳。因此柒莉,String.substring()方法能夠通過改變length和offset闻坚,而共享原始的character數(shù)組來創(chuàng)建一個新的String。對一個String來說兢孝,這些字段都是final型的字段窿凤。

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

字符串s2的offset的值為4,length的值為4跨蟹。但是雳殊,在舊的內(nèi)存模型下,對其他線程來說窗轩,看到offset擁有默認(rèn)的值0是不可能的夯秃,而且,稍后一點時間會看到正確的值4痢艺,好像字符串的值"/usr"變成了"/tmp"一樣仓洼。

舊的Java內(nèi)存模型允許這些行為,部分JVM已經(jīng)展現(xiàn)出這樣的行為了腹备。在新的Java內(nèi)存模型里面衬潦,這些是非法的。

在新的Java內(nèi)存模型中植酥,final字段是如何工作的

一個對象的final字段值是它的構(gòu)造方法里面設(shè)置的。假設(shè)對象被正確的構(gòu)造了弦牡,一旦對象被構(gòu)造友驮,在構(gòu)造方法里面設(shè)置給final字段的值在沒有同步的情況下對所有其他的線程都會可見。另外驾锰,引用這些final字段的對象或數(shù)組都將會看到final字段的最新值卸留。

對一個對象來說,被正確的構(gòu)造是什么意思呢椭豫?簡單來說:

它意味著這個正在構(gòu)造的對象的引用在構(gòu)造期間沒有被允許逸出耻瑟。(參見安全構(gòu)造技術(shù))旨指。

換句話說,不要讓其他線程在其他地方能夠看見一個構(gòu)造期間的對象引用喳整。不要指派給一個靜態(tài)字段谆构,不要作為一個listener注冊給其他對象等等。這些操作應(yīng)該在構(gòu)造方法之后完成框都,而不是構(gòu)造方法中來完成搬素。

class FinalFieldExample {
    final int x;
    int y;
    static FinalFieldExample f;
    public FinalFieldExample() {
        x = 3;
        y = 4;
    }

    static void writer() {
         f = new FinalFieldExample();
    }

    static void reader() {
        if (f != null) {
            int j = f.x;
            int j = f.y;
        }
    }
}

上面的類展示了final字段應(yīng)該如何使用。一個正在執(zhí)行reader方法的線程保證看到f.x的值為3魏保,因為是final字段熬尺。它不保證看到f.y的值為4,因為f.y不是final字段谓罗。如果FinalFieldExample的構(gòu)造方法像這樣

public FinalFieldExample() { // bad!
    x = 3;
    y = 4;
    // bad construction - allowing this to escape
    global.obj = this;
}

那么粱哼,從global.obj中讀取this的引用,線程不能保證讀取到的x的值為3.

能夠看到字段的正確的構(gòu)造值很不錯檩咱,但是揭措,如果字段本身就是一個引用,那么税手,你還是希望你的代碼能夠看到引用所指向的這個對象的最新值蜂筹。如果字段是final字段,那么這是能夠保證的芦倒。所以當(dāng)一個final指針指向一個數(shù)組艺挪,你不需要擔(dān)心線程能夠看到引用的最新值卻看不到引用所指向的數(shù)組的最新值。強(qiáng)調(diào)一下兵扬,這的“正確的”意思是“對象構(gòu)造方法結(jié)尾的最新的值”而不是“最新可用的值”麻裳。

現(xiàn)在,在講了如上的這段之后器钟,如果在一個線程構(gòu)造了一個不可變對象之后(對象僅包含final字段)津坑,你希望保證這個對象被其他線程正確的查看,你仍然需要使用同步才行傲霸。例如疆瑰,沒有其他的方式可以保證不可變對象的引用將被第二個線程看到。使用final字段的程序應(yīng)該仔細(xì)的調(diào)試昙啄,這需要深入而且仔細(xì)的理解并發(fā)在你的代碼中是如何被管理的穆役。

如果你使用JNI來改變你的final字段,這方面的行為是沒有定義的梳凛。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末耿币,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子韧拒,更是在濱河造成了極大的恐慌淹接,老刑警劉巖十性,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異塑悼,居然都是意外死亡劲适,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進(jìn)店門拢肆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來减响,“玉大人,你說我怎么就攤上這事郭怪≈荆” “怎么了?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵鄙才,是天一觀的道長颂鸿。 經(jīng)常有香客問我,道長攒庵,這世上最難降的妖魔是什么嘴纺? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮浓冒,結(jié)果婚禮上栽渴,老公的妹妹穿的比我還像新娘。我一直安慰自己稳懒,他們只是感情好闲擦,可當(dāng)我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著场梆,像睡著了一般墅冷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上或油,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天寞忿,我揣著相機(jī)與錄音,去河邊找鬼顶岸。 笑死腔彰,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的辖佣。 我是一名探鬼主播萍桌,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼凌简!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起恃逻,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤雏搂,失蹤者是張志新(化名)和其女友劉穎藕施,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體凸郑,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡裳食,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了芙沥。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诲祸。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖而昨,靈堂內(nèi)的尸體忽然破棺而出救氯,到底是詐尸還是另有隱情,我是刑警寧澤歌憨,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布着憨,位于F島的核電站,受9級特大地震影響务嫡,放射性物質(zhì)發(fā)生泄漏甲抖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一心铃、第九天 我趴在偏房一處隱蔽的房頂上張望准谚。 院中可真熱鬧,春花似錦去扣、人聲如沸柱衔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽秀存。三九已至,卻和暖如春羽氮,著一層夾襖步出監(jiān)牢的瞬間或链,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工档押, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留澳盐,地道東北人。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓令宿,卻偏偏與公主長得像叼耙,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子粒没,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理筛婉,服務(wù)發(fā)現(xiàn),斷路器癞松,智...
    卡卡羅2017閱讀 134,638評論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法爽撒,類相關(guān)的語法入蛆,內(nèi)部類的語法,繼承相關(guān)的語法硕勿,異常的語法哨毁,線程的語...
    子非魚_t_閱讀 31,602評論 18 399
  • java筆記第一天 == 和 equals ==比較的比較的是兩個變量的值是否相等,對于引用型變量表示的是兩個變量...
    jmychou閱讀 1,490評論 0 3
  • 從三月份找實習(xí)到現(xiàn)在源武,面了一些公司扼褪,掛了不少,但最終還是拿到小米粱栖、百度话浇、阿里、京東查排、新浪凳枝、CVTE、樂視家的研發(fā)崗...
    時芥藍(lán)閱讀 42,218評論 11 349
  • 在《荷馬史詩》中有這樣一個故事跋核,西西弗斯是人間最足智多謀的人岖瑰,他是科林斯的建城者和國王。當(dāng)宙斯擄走河神伊索普斯(A...
    每天進(jìn)步1點點閱讀 484評論 0 0