免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
java字符串池(string pool)和字符串堆(heap)內(nèi)存分配

java運(yùn)行環(huán)境有一個(gè)字符串池(string pool),由String類維護(hù)。

 

執(zhí)行語(yǔ)句 String str = "abc" 時(shí),首先查看字符串池中是否存在字符串"abc",如果存在則直接將"abc"地址賦給str ,如果不存在則先在字符串池中新建一個(gè)字符串"abc",然后再將其賦給str。

 

執(zhí)行語(yǔ)句 String str = new String("abc") 時(shí),不管字符串池中是否存在"abc",直接新建一個(gè)字符串"abc"(注意:新建的字符串"abc" 不是在字符串池中),然后將其賦給str。

 

前一語(yǔ)句的效率高,后一語(yǔ)句的效率低,因?yàn)樾陆ㄗ址加脙?nèi)存空間。String str = newString();創(chuàng)建了一個(gè)空字符串,與String str = new String("");相同。

 

public String intern()

返回字符串對(duì)象的規(guī)范化表示形式。一個(gè)初始為空的字符串池,它由類String私有地維護(hù)。當(dāng)調(diào)用intern()方法時(shí),如果字符串池中已經(jīng)包含一個(gè)等于此String對(duì)象的字符串 (用equals(Object)方法確定),則返回字符串池中的字符串。否則,將此String對(duì)象添加到字符串池中,并返回此String 對(duì)象的引用。它遵循以下規(guī)則:對(duì)于任意兩個(gè)字符串s 和 t,當(dāng)且僅當(dāng)s.equals(t)為true時(shí),s.intern() == t.intern() 才為true。

 

String.intern();

再補(bǔ)充一點(diǎn):存在于.class 文件中的常量池,在運(yùn)行期間被jvm(java virtualmachine)裝載,并且可以擴(kuò)充。String 的 intern()方法就是擴(kuò)充常量池的一個(gè)方法;當(dāng)一個(gè)String實(shí)例(instance)str調(diào)用intern()方法時(shí),java 查找常量池中是否有相同 unicode的字符串常量,如果有,則返回其引用,如果沒有,則在常量池中增加一個(gè)unicode 等于str 的字符串并返回其引用。

 

簡(jiǎn)單例子:

String s = "kvill";

String s1 = new String("kvill");

String s2 = new String("kvill");

System.out.println(s == s1);

s1.intern();

s2 = s2.intern();

System.out.println(s == s1);

System.out.println(s == s1.intern());

System.out.println(s == s2);

輸出結(jié)果為:

False

False  //雖然執(zhí)行了s1.intern(),但是它的返回值并沒有賦給s1

True

True

 

最后再破除一個(gè)錯(cuò)誤的理解:

有人說,"使用String.intern()方法可以將一個(gè)String類保存到一個(gè)全局的String表中,如果具有相同值的unicode字符串已經(jīng)在這個(gè)表中,那么該方法返回表中已有字符串的地址,如果在表中沒有相同unicode的字符串,則將自己的地址注冊(cè)到表中",如果我們把這個(gè)全局的String表理解成常量池的話,最后一句話"如果在表中沒有相同值的字符串,則將自己的地址注冊(cè)到表中"是錯(cuò)的。

簡(jiǎn)單例子:

String s1 = new String("kvill");

String s2 = s1.intern();

System.out.println(s1 == s1.intern());

System.out.println(s1 + " " + s2);

System.out.println(s2 == s1.intern());

輸出結(jié)果是:

False

kvill kvill

True

我們沒有聲明一個(gè)"kvill"常量,所以常量池中一開始沒有"kvill"的,當(dāng)我們調(diào)用s1.intern()后,就在常量池中新添加了一個(gè)"kvill"常量,原來的不在常量池中的"kvill"仍然存在,也就不是"把自己的地址注冊(cè)到常量池中"了。

 

 

例子1):

String str1 = "java"; // str1指向字符串池

String str2 = "blog"; // str2指向字符串池

 

String s = str1 + str2; // s是指向堆中值為"javablog"的對(duì)象,+運(yùn)算符會(huì)在堆中建立起來兩個(gè)String對(duì)象,這兩個(gè)對(duì)象分別是"java","blog",也就是說從字符串池中復(fù)制這兩個(gè)值,然后在堆中創(chuàng)建兩個(gè)對(duì)象,然后再建立對(duì)象s,然后將"javablog"的堆地址賦給s。// 這條語(yǔ)句總共創(chuàng)建了多少個(gè)對(duì)象?

 

System.out.println(s == "javablog"); // 結(jié)果為False

jvm(java virtual machine)確實(shí)對(duì)形如String str1 = "java";的String對(duì)象放在常量池中,但是它是在編譯時(shí)那么做的,而String s = str1 + str2;是在運(yùn)行時(shí)才知道的,也就是說str1 + str2 是在堆里創(chuàng)建的,所以結(jié)果為false了。

 

如果改成以下兩種方式:

String s = "java" + "blog";  //直接將"javablog"放入字符串池中

System.out.println(s == "javablog");  //結(jié)果為true

String s = str1 + "blog"; // 不放入字符串池,而是在堆中分配

System.out.println(s == "javablog"); // 結(jié)果為false

 

 

 

引用變量與對(duì)象的區(qū)別:

字符串"abc" 是一個(gè)String 對(duì)象,字符串池(pool of literalstrings)和堆(heap)中存放著字符串對(duì)象

 

一、引用變量與對(duì)象

A a;

這個(gè)語(yǔ)句聲明了一個(gè)類A的引用變量a,而對(duì)象一般通過new關(guān)鍵字創(chuàng)建,所以a僅僅是一個(gè)引用變量,而不是對(duì)象

 

二、java中所有的字符串文字(字符串常量)都是一個(gè)String類的對(duì)象。有人(特別是c程序員)在一些場(chǎng)合喜歡把字符串"當(dāng)做/看成"字符數(shù)組,這也沒有辦法,因?yàn)樽址c字符數(shù)組存在一些內(nèi)在的聯(lián)系。事實(shí)上,它與字符數(shù)組是兩種完全不同的對(duì)象。

 

三、字符串對(duì)象的創(chuàng)建

由于字符串對(duì)象的大量使用(它是一個(gè)對(duì)象,一般而言對(duì)象總是在堆(heap)中分配內(nèi)存),java中為了節(jié)省內(nèi)存空間和運(yùn)行時(shí)間(如比較字符串時(shí),==比 equals()方法快),在編譯階段就把所有的字符串文字放到一個(gè)字符串池(pool of literalstrings)中,而運(yùn)行時(shí)字符串池成為常量池的一部分。字符串池的好處,就是該池中所有相同的字符串常量被合并,只占用一個(gè)空間。

 

我們知道,對(duì)兩個(gè)引用變量,使用 == 判斷它們的值(引用)是否相等,即是否指向同一個(gè)對(duì)象:

String s1 = "abc";

String s2 = "abc";

if(s1 == s2) System.out.println("s1,s2 refer to the sameobject");

else System.out.println("trouble");

這里的輸出顯示,兩個(gè)字符串文字保存為一個(gè)對(duì)象,就是說,上面的代碼只在字符串池(string pool)中創(chuàng)建了一個(gè)對(duì)象。

 

現(xiàn)在看看String s = newString("abc");語(yǔ)句,這里"abc"本身就是pool中的一個(gè)對(duì)象,而在運(yùn)行時(shí)執(zhí)行newString()時(shí),將pool中的對(duì)象復(fù)制一份放到heap中,并且把heap中的這個(gè)對(duì)象的引用交給s持有。ok,這條語(yǔ)句就創(chuàng)建了2個(gè)String對(duì)象。

 

String s1 = new String("abc");

String s2 = new String("abc");

if(s1 == s2) { } // 不會(huì)執(zhí)行的語(yǔ)句

這里用 ==判斷就可知,雖然兩個(gè)對(duì)象的"內(nèi)容"相同(equals()判斷),但兩個(gè)引用變量所持有的引用不同,上面的代碼創(chuàng)建了幾個(gè)StringObject? (三個(gè),pool中一個(gè),heap中兩個(gè))

 

 

 

綜上所述:

創(chuàng)建字符串有兩種方式:兩種內(nèi)存區(qū)域(pool vs heap)

1. "" 引號(hào)創(chuàng)建的字符串在字符串池中

2. new, new關(guān)鍵字創(chuàng)建字符串時(shí)首先查看字符串池(stringpool)中是否有相同值的字符串,如果有,則拷貝一份到堆(heap)中,然后返回堆中的地址;如果字符串池中沒有,則在堆中創(chuàng)建一份,然后返回堆(heap)中的地址(注意,此時(shí)不需要從堆中復(fù)制到池中,否則,將使得堆中的字符串永遠(yuǎn)是池中的子集,導(dǎo)致浪費(fèi)字符串池的內(nèi)存空間)

3. 對(duì)字符串進(jìn)行賦值時(shí),如果右操作數(shù)含有一個(gè)或一個(gè)以上的字符串引用時(shí),則在堆中再建立一個(gè)字符串對(duì)象,返回引用;如Strings = str1 + "blog";

比較兩個(gè)已經(jīng)存在于字符串池中字符串對(duì)象可以用 == 進(jìn)行,擁有比equals操作更快的速度。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
全面理解Java中的String數(shù)據(jù)類型
深入Java核心 Java內(nèi)存分配原理精講(1) - 51CTO.COM
Z)JAVA?字符串使用
Java內(nèi)存結(jié)構(gòu)【整理】
深入研究java對(duì)String字符串對(duì)象的創(chuàng)建以及管理
解析Java String字符串對(duì)象的創(chuàng)建及管理(2)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服