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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

String类型的认识以及编译器优化

發(fā)布時(shí)間:2023/12/31 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 String类型的认识以及编译器优化 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Java中String不是基本類型,但是有些時(shí)候和基本類型差不多,如String b =?"tao"?;?可以對(duì)變量直接賦值,而不用?new?一個(gè)對(duì)象(當(dāng)然也可以用?new)。所以String這個(gè)類型值得好好研究下。

Java中的變量和基本類型的值存放于棧內(nèi)存,而new出來(lái)的對(duì)象本身存放于堆內(nèi)存,指向?qū)ο蟮囊眠€是存放在棧內(nèi)存。例如如下的代碼:

int??i=1;

????String?s?=??new??String(?"Hello World"?);

變量i和s以及1存放在棧內(nèi)存,而s指向的對(duì)象”Hello World”存放于堆內(nèi)存。

?

?

?

?

棧內(nèi)存的一個(gè)特點(diǎn)是數(shù)據(jù)共享,這樣設(shè)計(jì)是為了減小內(nèi)存消耗,前面定義了i=1,i和1都在棧內(nèi)存內(nèi),如果再定義一個(gè)j=1,此時(shí)將j放入棧內(nèi)存,然后查找棧內(nèi)存中是否有1,如果有則j指向1。如果再給j賦值2,則在棧內(nèi)存中查找是否有2,如果沒(méi)有就在棧內(nèi)存中放一個(gè)2,然后j指向2。也就是如果常量在棧內(nèi)存中,就將變量指向該常量,如果沒(méi)有就在該棧內(nèi)存增加一個(gè)該常量,并將變量指向該常量。

?

?

如果j++,這時(shí)指向的變量并不會(huì)改變,而是在棧內(nèi)尋找新的常量(比原來(lái)的常量大1),如果棧內(nèi)存有則指向它,如果沒(méi)有就在棧內(nèi)存中加入此常量并將j指向它。這種基本類型之間比較大小和我們邏輯上判斷大小是一致的。如定義i和j是都賦值1,則i==j結(jié)果為true。==用于判斷兩個(gè)變量指向的地址是否一樣。i==j就是判斷i指向的1和j指向的1是同一個(gè)嗎?當(dāng)然是了。對(duì)于直接賦值的字符串常量(如String s=“Hello World”;中的Hello World)也是存放在棧內(nèi)存中,而new出來(lái)的字符串對(duì)象(即String對(duì)象)是存放在堆內(nèi)存中。如果定義String s=“Hello World”和String w=“Hello World”,s==w嗎?肯定是true,因?yàn)樗麄冎赶虻氖峭粋€(gè)Hello World。

?

?

堆內(nèi)存沒(méi)有數(shù)據(jù)共享的特點(diǎn),前面定義的String?s?=??new??String(?"Hello World"?);后,變量s在棧內(nèi)存內(nèi),Hello World?這個(gè)String對(duì)象在堆內(nèi)存內(nèi)。如果定義String w =?new??String(?"Hello World"?);,則會(huì)在堆內(nèi)存創(chuàng)建一個(gè)新的String對(duì)象,變量w存放在棧內(nèi)存,w指向這個(gè)新的String對(duì)象。堆內(nèi)存中不同對(duì)象(指同一類型的不同對(duì)象)的比較如果用==則結(jié)果肯定都是false,比如s==w?當(dāng)然不等,s和w指向堆內(nèi)存中不同的String對(duì)象。如果判斷兩個(gè)String對(duì)象相等呢?用equals方法。

?

?

?

說(shuō)了這么多只是說(shuō)了這道題的鋪墊知識(shí),還沒(méi)進(jìn)入主題,下面分析這道題。?MESSAGE?成員變量及其指向的字符串常量肯定都是在棧內(nèi)存里的,變量?a?運(yùn)算完也是指向一個(gè)字符串“?taobao?”啊?是不是同一個(gè)呢?這涉及到編譯器優(yōu)化問(wèn)題。對(duì)于字符串常量的相加,在編譯時(shí)直接將字符串合并,而不是等到運(yùn)行時(shí)再合并。也就是說(shuō)

String a =??"tao"?+?"bao"?;和String a =??"taobao"?;編譯出的字節(jié)碼是一樣的。所以等到運(yùn)行時(shí),根據(jù)上面說(shuō)的棧內(nèi)存是數(shù)據(jù)共享原則,a和MESSAGE指向的是同一個(gè)字符串。而對(duì)于后面的(b+c)又是什么情況呢?b+c只能等到運(yùn)行時(shí)才能判定是什么字符串,編譯器不會(huì)優(yōu)化,想想這也是有道理的,編譯器怕你對(duì)b的值改變,所以編譯器不會(huì)優(yōu)化。運(yùn)行時(shí)b+c計(jì)算出來(lái)的"taobao"和棧內(nèi)存里已經(jīng)有的"taobao"是一個(gè)嗎?不是。b+c計(jì)算出來(lái)的"taobao"應(yīng)該是放在堆內(nèi)存中的String對(duì)象。這可以通過(guò)System.?out?.println( (b+c)==MESSAGE?);的結(jié)果為false來(lái)證明這一點(diǎn)。如果計(jì)算出來(lái)的b+c也是在棧內(nèi)存,那結(jié)果應(yīng)該是true。Java對(duì)String的相加是通過(guò)StringBuffer實(shí)現(xiàn)的,先構(gòu)造一個(gè)StringBuffer里面存放”tao”,然后調(diào)用append()方法追加”bao”,然后將值為”taobao”的StringBuffer轉(zhuǎn)化成String對(duì)象。StringBuffer對(duì)象在堆內(nèi)存中,那轉(zhuǎn)換成的String對(duì)象理所應(yīng)當(dāng)?shù)囊彩窃诙褍?nèi)存中。下面改造一下這個(gè)語(yǔ)句System.?out.println( (b+c).intern()==?MESSAGE?);結(jié)果是true,?intern()?方法會(huì)先檢查?String?池?(?或者說(shuō)成棧內(nèi)存?)?中是否存在相同的字符串常量,如果有就返回。所以?intern()返回的就是MESSAGE指向的"taobao"。再把變量b和c的定義改一下,

final??String?b =??"tao"?;

?????????final??String?c =??"bao"?;

????????????

???????System.?out?.println( (b+c)==?MESSAGE?);

現(xiàn)在b和c不可能再次賦值了,所以編譯器將b+c編譯成了”taobao”。因此,這時(shí)的結(jié)果是true。

在字符串相加中,只要有一個(gè)是非final類型的變量,編譯器就不會(huì)優(yōu)化,因?yàn)檫@樣的變量可能發(fā)生改變,所以編譯器不可能將這樣的變量替換成常量。例如將變量b的final去掉,結(jié)果又變成了false。這也就意味著會(huì)用到StringBuffer對(duì)象,計(jì)算的結(jié)果在堆內(nèi)存中。

????如果對(duì)指向堆內(nèi)存中的對(duì)象的String變量調(diào)用intern()會(huì)怎么樣呢?實(shí)際上這個(gè)問(wèn)題已經(jīng)說(shuō)過(guò)了,(b+c).intern(),b+c的結(jié)果就是在堆內(nèi)存中。對(duì)于指向棧內(nèi)存中字符串常量的變量調(diào)用intern()返回的還是它自己,沒(méi)有多大意義。它會(huì)根據(jù)堆內(nèi)存中對(duì)象的值,去查找String池中是否有相同的字符串,如果有就將變量指向這個(gè)string池中的變量。

String a = "tao"+"bao";

???????String b = new String("taobao");

?????

??????System.out.println(a==MESSAGE);?//true

??????System.out.println(b==MESSAGE);??//false

?????

??????b = b.intern();

??????System.out.println(b==MESSAGE); //true

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

轉(zhuǎn)載于:https://www.cnblogs.com/nxjblog/p/10574550.html

總結(jié)

以上是生活随笔為你收集整理的String类型的认识以及编译器优化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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