Posted on 2009-06-06 09:02
thui 閱讀(2945)
評論(4) 編輯 收藏 所屬分類:
java技術
java的String類型,你徹底理解嗎?看看下面的題目:
String s=”abc”;
String s1=”abc”;
String s2=new String(“abc”);
String s3=s2.intern();
System.out.println(s1==s);
System.out.println(s1==s2);
System.out.println(s1==s3);
上面的題目會打印什么?
如果你不確定,那么請打開Eclipse,敲入上面的程序運行一下,你會發現打印的是true、false、true,為什么會有上面的打印呢?了解了下面關于java String的細節后,就會明白:
1.雙引號字符串是常量字符串,在java文件編譯的時候就放在虛擬機的常量池中,比如s,當創建abc時,發現常量池中沒有就在常量池中創建abc并把abc的地址賦給s,當再創建s1時,首先會去常量池中去查找abc是否存在,如果存在就把常量池中abc的地址賦給s1,所以比較s和s1的地址是相等的
2.如果用new的方法創建一個String時,就和s=”abc”不一樣了,s2=new String(“abc”)是在程序運行時創建,不是創建在常量池而是和其他java對象一樣在java堆上創建,因此它的地址和s不用.
3.如果運行時想把一個String創建到常量池中,java提供了一種方法,這個方法也會先檢查常量池是否存在abc,若存在返回abc在池中的地址。所以最后一個打印時true
在看下面的題目:
String s1=”ab”;
String s2=”cd”;
String s3=”abcd”;
String s4=s1+s2;
String s5=”ab”+"cd”;
System.out.println(s4==s3);
System.out.println(s5==s3);
這是又會是什么結果呢?答案是false,true,這個題目說明兩個字符串常量連接和還是字符串常量,但是只要其中一個是變量,就和new的效果一樣了,即是在堆上創建
說完了java的String類型,我們最后看看java函數參數的傳遞,到底是值傳遞還是引用傳遞呢?一般的說法是對于基本類型比如int、char是值傳遞,對于對象類型是引用傳遞。這種說法沒錯,但是請看下面的例子:
String s=”abc”;
change(s);
System.out.println(s);
public void change(String str)
{
str=”abcd”;
}
上面的程序會有什么結果呢?打印abc還是abcd,運行程序會發現打印的是abc,完了,似乎不合乎常理,按理說String 也是對象,應該是引用傳遞才對啊,有的同學知道java的String類型是不可變類型,會得出結果abc,具體解釋是String就相當于是char[]的包裝類。包裝類的特質之一就是在對其值進行操作時會體現出其對應的基本類型的性質。在參數傳遞時,包裝類就是如此體現的。所以,對于String在這種情況下的展現結果的解釋就自然而然得出了。同樣的,Integer、Float等這些包裝類和String在這種情況下的表現是相同的。下面從函數參數傳遞的方式來理解也可以得出相同的結果。
java的參數傳遞本質上都可以認為是值傳遞,對基本類型自然不必說,對于對象類型,傳遞的是對象的地址,地址是個數字,也是基本類型,所以也還是值傳遞的, 有了這個基礎,上面的題目可以這樣理解,s是字符串abc的地址,調用change方法時,把s的拷貝賦給str,即str也指向abc,但是在方法里又把str指向abcd,str就是abcd的地址了,但是s還是指向的abc。