国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

String對象創建個數

2019-11-17 03:57:57
字體:
來源:轉載
供稿:網友
s = new String("xyz");創建了幾個String Object?兩個對象,一個是“xyx”,一個是指向“xyx”的引用對象s。

String s="你好";int i=3; s=i+s; 這個表達式對嗎?在java中會提示數據類型不匹配。因為string是類!正確做法: s+="3" 或者 s+='3'或者 s+=(char)i;

我們要引入另外一種創建String對象的方式的討論——引號內包含文本。這種方式是String特有的,并且它與new的方式存在很大區別。

在JAVA虛擬機(JVM)中存在著一個字符串池,其中保存著很多String對象,并且可以被共享使用,因此它提高了效率。String a="abc";,這行代碼被執行的時候,JAVA虛擬機首先在字符串池中查找是否已經存在了值為"abc"的這么一個對象,判斷依據是String類equals(Object obj)方法的返回值。如果有,則不再創建新的對象,直接返回已存在對象的引用;如果沒有,則先創建這個對象,然后把它加入到字符串池中,再將它的引用返回。

字符串對象的創建:由于字符串對象的大量使用[它是一個對象,一般而言對象總是在heap分配內存],Java中為了節省內存空間和運行時間[如比較字符串時,==比equals()快],在編譯階段就把所有的字符串文字放到一個文字池中,而運行時文字池成為常量池的一部分。文字池的好處,就是該池中所有相同的字符串常量被合并,只占用一個空間。我們知道,對兩個引用變量,使用==判斷它們的值[引用]是否相等,即指向同一個對象:

    現在看String s = new String("abc");語句,這里"abc"本身就是pool中的一個對象,而在運行時執行new String()時,將pool中的對象復制一份放到heap中,并且把heap中的這個對象的引用交給s持有。ok,這條語句就創建了2個String對象。

    String s1 = new String("abc") ;String s2 = new String("abc") ;if( s1 == s2 ){ //不會執行的語句}

    //創建了幾個String Object? [三個,pool中一個,heap中2個。]

只有使用引號包含文本的方式創建的String對象之間使用“+”連接產生的新對象才會被加入字符串池中。對于所有包含new方式新建對象(包括null)的“+”連接表達式,它所產生的新對象都不會被加入字符串池中。

1.==表示引用自同一對象,equals()表示值相等。

String str1 = "abc";引用的對象在棧(或者叫String池)中。

String str1 =new String ("abc"); 引用的對象在內存/堆中。

2.String str1 =  "string";在棧中

  String str3 =  "str";在棧中

  String str4 = "ing";在棧中

  String str2 = str3+str4; 在堆中,因為+號的作用是返回另外一個新建的String對象,而不是在棧中找string這個值。如果是String str2 = "str"+"ing";那最后的結果就在棧中。str1==str2為true。

但是有一種情況需要引起我們的注意。請看下面的代碼:

public class StringStaticTest {       

    public static final String A = "ab"; // 常量A

    public static final String B = "cd"; // 常量B

    public static void main(String[] args) {

         String s = A + B;  // 將兩個常量用+連接對s進行初始化  

         String t = "abcd";    

        if (s == t) {    

             System.out.PRintln("s等于t,它們是同一個對象");    

         } else {    

             System.out.println("s不等于t,它們不是同一個對象");    

         }    

     }    

}   

這段代碼的運行結果如下:

s等于t,它們是同一個對象

原因是在上面的例子中,A和B都是常量,值是固定的,因此s的值也是固定的,它在類被編譯時就已經確定了。也就是說:String s=A+B;  等同于:String s="ab"+"cd";

我對上面的例子稍加改變看看會出現什么情況:

public class StringStaticTest {        

    public static final String A; // 常量A

    public static final String B;    // 常量B

    static {    

         A = "ab";    

         B = "cd";    

     }    

     public static void main(String[] args) {    

        // 將兩個常量用+連接對s進行初始化    

         String s = A + B;    

         String t = "abcd";    

        if (s == t) {    

             System.out.println("s等于t,它們是同一個對象");    

         } else {    

             System.out.println("s不等于t,它們不是同一個對象");    

         }    

     }    

}

它的運行結果是這樣:

s不等于t,它們不是同一個對象

只是做了一點改動,結果就和剛剛的例子恰好相反。我們再來分析一下。A和B雖然被定義為常量(只能被賦值一次),但是它們都沒有馬上被賦值。在運算出s的值之前,他們何時被賦值,以及被賦予什么樣的值,都是個變數。因此A和B在被賦值之前,性質類似于一個變量。那么s就不能在編譯期被確定,而只能在運行時被創建了。

最后我們再來說說String對象在JAVA虛擬機(JVM)中的存儲,以及字符串池與堆(heap)和棧(stack)的關系。我們首先回顧一下堆和棧的區別:

棧(stack):主要保存基本類型(或者叫內置類型)(char、byte、short、int、long、float、double、boolean)和對象的引用,數據可以共享,速度僅次于寄存器(register),快于堆。

堆(heap):用于存儲對象。

我們查看String類的源碼就會發現,它有一個value屬性,保存著String對象的值,類型是char[],這也正說明了字符串就是字符的序列。當執行String a="abc";時,JAVA虛擬機會在棧中創建三個char型的值'a'、'b'和'c',然后在堆中創建一個String對象,它的值(value)是剛才在棧中創建的三個char型值組成的數組{'a','b','c'},最后這個新創建的String對象會被添加到字符串池中。

如果我們接著執行String b=new String("abc");代碼,由于"abc"已經被創建并保存于字符串池中,因此JAVA虛擬機只會在堆中新創建一個String對象,但是它的值(value)是共享前一行代碼執行時在棧中創建的三個char型值值'a'、'b'和'c'。

說到這里,我們對于篇首提出的String str=new String("abc")為什么是創建了兩個對象這個問題就已經相當明了了。

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/yakihappy/archive/2009/03/10/3977169.aspx



本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/Foxalien/archive/2009/12/18/5029470.aspx
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 全南县| 额济纳旗| 绥江县| 蓬莱市| 荆州市| 明星| 景东| 潢川县| 南昌市| 建瓯市| 汪清县| 巴东县| 定襄县| 平乐县| 丰台区| 博野县| 林州市| 无锡市| 卢氏县| 汝南县| 陕西省| 大新县| 偃师市| 芜湖县| 黄浦区| 辽宁省| 三河市| 明溪县| 泰来县| 扶绥县| 平安县| 深圳市| 襄垣县| 枣阳市| 柞水县| 博罗县| 盘锦市| 柳江县| 林口县| 宜兴市| 梅州市|