日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

深入Java核心 Java内存分配原理精讲(3)

發(fā)布時間:2023/12/15 java 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入Java核心 Java内存分配原理精讲(3) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

String常量池問題的幾個例子

下面是幾個常見例子的比較分析和理解:

  • String?a?=?"a1";? ?

  • String?b?=?"a"?+?1;? ?

  • System.out.println((a?==?b));?//result?=?true??

  • String?a?=?"atrue";? ?

  • String?b?=?"a"?+?"true";? ?

  • System.out.println((a?==?b));?//result?=?true??

  • String?a?=?"a3.4";? ?

  • String?b?=?"a"?+?3.4;? ?

  • System.out.println((a?==?b));?//result?=?true?

  • 分析:JVM對于字符串常量的"+"號連接,將程序編譯期,JVM就將常量字符串的"+"連接優(yōu)化為連接后的值,拿"a" + 1來說,經(jīng)編譯器優(yōu)化后在class中就已經(jīng)是a1。在編譯期其字符串常量的值就確定下來,故上面程序最終的結(jié)果都為true。

  • String?a?=?"ab";? ?

  • String?bb?=?"b";? ?

  • String?b?=?"a"?+?bb;? ?

  • System.out.println((a?==?b));?//result?=?false?

  • 分析:JVM對于字符串引用,由于在字符串的"+"連接中,有字符串引用存在,而引用的值在程序編譯期是無法確定的,即"a" + bb無法被編譯器優(yōu)化,只有在程序運(yùn)行期來動態(tài)分配并將連接后的新地址賦給b。所以上面程序的結(jié)果也就為false。

  • String?a?=?"ab";? ?

  • final?String?bb?=?"b";? ?

  • String?b?=?"a"?+?bb;? ?

  • System.out.println((a?==?b));?//result?=?true?

  • 分析:和[3]中唯一不同的是bb字符串加了final修飾,對于final修飾的變量,它在編譯時被解析為常量值的一個本地拷貝存儲到自己的常量 池中或嵌入到它的字節(jié)碼流中。所以此時的"a" + bb和"a" + "b"效果是一樣的。故上面程序的結(jié)果為true。

  • String?a?=?"ab";? ?

  • final?String?bb?=?getBB();? ?

  • String?b?=?"a"?+?bb;? ?

  • System.out.println((a?==?b));?//result?=?false???

  • private?static?String?getBB()?{ ?

  • return?"b";? ?

  • }?

  • 分析:JVM對于字符串引用bb,它的值在編譯期無法確定,只有在程序運(yùn)行期調(diào)用方法后,將方法的返回值和"a"來動態(tài)連接并分配地址為b,故上面 程序的結(jié)果為false。

    通過上面4個例子可以得出得知:

    String? s? =? "a" + "b" + "c";?
    ??
    就等價于String s = "abc";??

    String? a? =? "a";???
    String? b? =? "b";???
    String? c? =? "c";???
    String? s? =?? a? +? b? +? c;?

    這個就不一樣了,最終結(jié)果等于:?
    ?

  • StringBuffer?temp?=?new?StringBuffer();??? ?

  • temp.append(a).append(b).append(c);??? ?

  • String?s?=?temp.toString();?

  • 由上面的分析結(jié)果,可就不難推斷出String 采用連接運(yùn)算符(+)效率低下原因分析,形如這樣的代碼:

  • public?class?Test?{ ?

  • public?static?void?main(String?args[])?{ ?

  • String?s?=?null; ?

  • for(int?i?=?0;?i?<?100;?i++)?{ ?

  • s?+=?"a"; ?

  • } ?

  • } ?

  • }?

  • 每做一次 + 就產(chǎn)生個StringBuilder對象,然后append后就扔掉。下次循環(huán)再到達(dá)時重新產(chǎn)生個StringBuilder對象,然后 append 字符串,如此循環(huán)直至結(jié)束。如果我們直接采用 StringBuilder 對象進(jìn)行 append 的話,我們可以節(jié)省 N - 1 次創(chuàng)建和銷毀對象的時間。所以對于在循環(huán)中要進(jìn)行字符串連接的應(yīng)用,一般都是用StringBuffer或StringBulider對象來進(jìn)行 append操作。

    String對象的intern方法理解和分析:

  • public?class?Test4?{ ?

  • private?static?String?a?=?"ab";? ?

  • public?static?void?main(String[]?args){ ?

  • String?s1?=?"a"; ?

  • String?s2?=?"b"; ?

  • String?s?=?s1?+?s2; ?

  • System.out.println(s?==?a);//false??

  • System.out.println(s.intern()?==?a);//true????

  • } ?

  • }?

  • 這里用到Java里面是一個常量池的問題。對于s1+s2操作,其實是在堆里面重新創(chuàng)建了一個新的對象,s保存的是這個新對象在堆空間的的內(nèi)容,所 以s與a的值是不相等的。而當(dāng)調(diào)用s.intern()方法,卻可以返回s在常量池中的地址值,因為a的值存儲在常量池中,故s.intern和a的值相等。

    總結(jié)

    棧中用來存放一些原始數(shù)據(jù)類型的局部變量數(shù)據(jù)和對象的引用(String,數(shù)組.對象等等)但不存放對象內(nèi)容

    堆中存放使用new關(guān)鍵字創(chuàng)建的對象.

    字符串是一個特殊包裝類,其引用是存放在棧里的,而對象內(nèi)容必須根據(jù)創(chuàng)建方式不同定(常量池和堆).有的是編譯期就已經(jīng)創(chuàng)建好,存放在字符串常 量池中,而有的是運(yùn)行時才被創(chuàng)建.使用new關(guān)鍵字,存放在堆中。


    轉(zhuǎn)載于:https://blog.51cto.com/wuqinglong/1431774

    總結(jié)

    以上是生活随笔為你收集整理的深入Java核心 Java内存分配原理精讲(3)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。