黄色网址大全免费-黄色网址你懂得-黄色网址你懂的-黄色网址有那些-免费超爽视频-免费大片黄国产在线观看

專注Java教育14年 全國(guó)咨詢/投訴熱線:400-8080-105
動(dòng)力節(jié)點(diǎn)LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁(yè) 學(xué)習(xí)攻略 Java學(xué)習(xí) Java編程技術(shù)分享之字符串字面量

Java編程技術(shù)分享之字符串字面量

更新時(shí)間:2020-06-03 16:13:31 來(lái)源:動(dòng)力節(jié)點(diǎn) 瀏覽2298次

字符串是不可變的

究竟什么使字符串字面量這么特殊?首先,記住重要的一點(diǎn)是字符串對(duì)象是不可變的。

這就意味著一旦創(chuàng)建,一個(gè)字符串對(duì)象就不能被改變(還是可以通過(guò)反射來(lái)改變)。

不可變?不能被更改?那怎么解釋這段代碼。

public?class?ImmutableStrings
{
????public?static?void?main(String[]?args)
????{
????????String?start?=?"Hello";
????????String?end?=?start.concat("?World!");
????????System.out.println(end);
????}
}

//?Output
Hello?World!

看這段代碼,字符串被改變了嗎,還是沒有?事實(shí)上,這段代碼中并沒有字符串對(duì)象被改變。

我們首先將“Hello”賦值給start變量,為了實(shí)現(xiàn)這步,需要在堆中創(chuàng)建一個(gè)對(duì)象,并把它的引用存儲(chǔ)在start中。接下來(lái),我們?cè)谶@個(gè)對(duì)象上調(diào)用concat(String)方法。進(jìn)行到這里Java耍了一個(gè)小把戲,如果我們查看String的API說(shuō)明,會(huì)發(fā)現(xiàn)其中對(duì)于concat(String)方法有如下的描述:

Java編程技術(shù)分享之字符串字面量

方法描述:將指定字符串連接在這個(gè)字符串的結(jié)尾。

如果長(zhǎng)度為0,則返回這個(gè)字符串對(duì)象。否則就創(chuàng)建一個(gè)新的字符串對(duì)象,表示這個(gè)字符串序列由原字符串對(duì)象和參數(shù)字符串二者所表示的字符串序列拼接而成。

你肯定看到了,當(dāng)你將兩個(gè)字符串做拼接操作時(shí),實(shí)際上并沒有改變?cè)瓕?duì)象,而是直接創(chuàng)建了一個(gè)包含原始對(duì)象的新的對(duì)象,并且將另一個(gè)字符串拼在了后面。

我們上面那段代碼就是這么執(zhí)行的,start變量所引用的字符串對(duì)象并沒有改變,如果在調(diào)用concat方法之后System.out.println(start);,會(huì)發(fā)現(xiàn)start仍然指向的是“Hello”。

這時(shí)候你可能想到了字符串中的“+”操作符,事實(shí)上字符串的“+”操作也是和concat做了同樣的事情(“+”操作實(shí)際上是new了一個(gè)StringBuilder對(duì)象,然后調(diào)用append方法)。

字符串的存儲(chǔ)——字符串常量池

你或許聽說(shuō)過(guò)“字符串常量池”這個(gè)概念,究竟什么是字符串常量池?有人說(shuō)是一個(gè)字符串對(duì)象容器。答案很接近了,但是不完全正確。

事實(shí)上他是一用來(lái)保存字符串對(duì)象引用的容器。

即使字符串是不可變的,它仍然和Java中的其他對(duì)象一樣。對(duì)象都是創(chuàng)建在堆中,字符串也不例外。

所以字符串常量池仍然依靠堆,他們存儲(chǔ)的只是堆中字符串的引用。

目前還沒有解釋這個(gè)池到底是什么,或者它為何存在。

好吧,因?yàn)樽址畬?duì)象是不可變的,所以復(fù)制多個(gè)引用來(lái)“共享”這個(gè)字符串是安全的。下面來(lái)看一個(gè)例子:

public?class?ImmutableStrings
{
????public?static?void?main(String[]?args)
????{
????????String?one?=?"someString";
????????String?two?=?"someString";
????????
????????System.out.println(one.equals(two));
????????System.out.println(one?==?two);
????}
}

//?Output

true
true

在這個(gè)例子中,實(shí)在沒有必要為一個(gè)相同的字符串對(duì)象創(chuàng)建兩個(gè)實(shí)例。如果字符串像StringBuffer一樣是可變的,那么我們會(huì)被迫創(chuàng)建兩個(gè)對(duì)象(如果不這樣做的話,通過(guò)一個(gè)引用改變它的值,將會(huì)導(dǎo)致其他引用的值也同樣改變,從而可能發(fā)生錯(cuò)誤)。

但是,我們知道字符串對(duì)象是不能被改變的,我們可以安全地通過(guò)兩個(gè)引用one和two來(lái)使用一個(gè)字符串對(duì)象。

這個(gè)工作是通過(guò)字符串常量池完成的,下面來(lái)看一下它是如何完成的:

當(dāng)一個(gè).java文件被編譯成.class文件時(shí),和所有其他常量一樣,每個(gè)字符串字面量都通過(guò)一種特殊的方式被記錄下來(lái)。

當(dāng)一個(gè).class文件被加載時(shí)(注意加載發(fā)生在初始化之前),JVM在.class文件中尋找字符串字面量。

當(dāng)找到一個(gè)時(shí),JVM會(huì)檢查是否有相等的字符串在常量池中存放了堆中引用。

如果找不到,就會(huì)在堆中創(chuàng)建一個(gè)對(duì)象,然后將它的引用存放在池中的一個(gè)常量表中。

一旦一個(gè)字符串對(duì)象的引用在常量池中被創(chuàng)建,這個(gè)字符串在程序中的所有字面量引用都會(huì)被常量池中已經(jīng)存在的那個(gè)引用代替。

所以,在上面的例子中字符串常量池中只有一個(gè)引用,就是“someString”這個(gè)字符串對(duì)象的引用。

局部變量one和two都被賦予了同一個(gè)字符串對(duì)象的引用。可以通過(guò)程序的輸出來(lái)驗(yàn)證。

equals方法檢查的是兩個(gè)字符串對(duì)象是否包含相同的數(shù)據(jù)(“someString”),而“==”操作符作用在對(duì)象上比較的是引用是否相同,這意味著只有兩個(gè)引用指向的是同一個(gè)對(duì)象才會(huì)返回true。

所以例子中的兩個(gè)引用是相等的。從輸出可以看到,局部變量one和two不僅包含相同的數(shù)據(jù),而且還指向相同的對(duì)象。

無(wú)圖無(wú)真相,來(lái)看一下他們之間的關(guān)系:

Java編程技術(shù)分享之字符串字面量

注意,對(duì)于字符串字面量有一點(diǎn)比較特殊。通過(guò)“new”關(guān)鍵字構(gòu)建時(shí)一種不同的方式。

下面舉一個(gè)例子:

public?class?ImmutableStrings
{
????public?static?void?main(String[]?args)
????{
????????String?one?=?"someString";
????????String?two?=?new?String("someString");
????????
????????System.out.println(one.equals(two));
????????System.out.println(one?==?two);
????}
}
//?Output

true
false

在這個(gè)例子中,可以看到由于關(guān)鍵字“new”,最后的結(jié)果有一點(diǎn)不同。

此例中,兩個(gè)字符串字面量仍然被放進(jìn)了常量池的常量表中,但是當(dāng)使用“new”時(shí),JVM就會(huì)在運(yùn)行時(shí)創(chuàng)建一個(gè)新對(duì)象,而不是使用常量表中的引用。

雖然例子中的兩個(gè)字符串引用所指向的對(duì)象包含相同的數(shù)據(jù)“someString”,但是這兩個(gè)對(duì)象并不相同。

這一點(diǎn)可以從輸出看出來(lái),equals方法返回了true,而檢查引用是否相等的“==”返回false。

這表明兩個(gè)變量指向的是兩個(gè)不同的字符串對(duì)象。

如果你想看圖形化的表示,下面就是。要記住引用到常量池的字符串對(duì)象是在類加載的時(shí)候創(chuàng)建的,而另一個(gè)對(duì)象是在運(yùn)行時(shí),當(dāng)“new String”語(yǔ)句被執(zhí)行時(shí)。

Java編程技術(shù)分享之字符串字面量

如果你想得到兩個(gè)引用到相同對(duì)象的局部變量,你可以使用String類中的定義的intern()方法。

調(diào)用two.intern()后,會(huì)在字符串常量池中尋找是否有值相等的對(duì)象引用。

如果有的話,就會(huì)返回這個(gè)引用,然后你可以把它賦給局部變量。

如果這么做的化,局部變量one和two都是同一個(gè)對(duì)象的引用,并且在字符串常量池中也存有一個(gè)引用,就如同第一張圖那樣。這時(shí),在運(yùn)行時(shí)創(chuàng)建的第二個(gè)字符串對(duì)象將會(huì)被GC回收。

以上就是動(dòng)力節(jié)點(diǎn)java培訓(xùn)機(jī)構(gòu)的小編針對(duì)“Java編程技術(shù)分享之字符串字面量”的內(nèi)容進(jìn)行的回答,希望對(duì)大家有所幫助,如有疑問(wèn),請(qǐng)?jiān)诰€咨詢,有專業(yè)老師隨時(shí)為你服務(wù)。

提交申請(qǐng)后,顧問(wèn)老師會(huì)電話與您溝通安排學(xué)習(xí)

免費(fèi)課程推薦 >>
技術(shù)文檔推薦 >>
主站蜘蛛池模板: 欧美日韩国产成人综合在线影院 | 亚洲 欧美 日韩 在线 香蕉 | 在线播放你懂的 | 日韩拍拍拍| 国产麻豆免费 | 日韩欧美片 | 又黄又免费 | 青青草欧美 | 日日射天天射 | 欧美精彩狠狠色丁香婷婷 | 成人黄18免费视频 | 人人看人人搞 | 2018天天爽天天玩天天拍 | 日韩在线欧美在线 | 久草手机在线观看 | 在线中文字幕视频 | 伊人天堂在线 | 青春草视频在线观看免费 | 72式性无遮挡免费视频观看 | 国产成人精品福利网站人 | 波多野结衣xxxx性精品 | 亚洲成人网在线播放 | 成人免费视屏 | 写真片 理论 在线播放 | 亚洲三级国产 | 国产在线观看99 | 成人亚洲网站 | 人人干人人干 | 久久天堂夜夜一本婷婷麻豆 | 在线 | 一区二区三区 | 碰碰碰人人澡人人爱摸 | 国内成人免费视频 | 草草草网站| 欧美精品专区免费观看 | 欧美午夜在线播放 | 狠狠操狠狠干 | 永久网站色视频在线观看免费 | 国产在线一卡二卡 | 成人久久18免费游戏网站 | 国产精品成人影院 | 涩涩涩丁香色婷五月网视色 |