一、創建。
好了,知道String是非可變類以后,我們可以進一步了解String的構造方式了。創建一個Stirng對象,主要就有以下兩種方式:
- String str1 = new String("abc");
- Stirng str2 = "abc";
雖然兩個語句都是返回一個String對象的引用,但是jvm對兩者的處理方式是不一樣的。對于第一種,jvm會馬上在heap中創建一個String對象,然后將該對象的引用返回給用戶。對于第二種,jvm首先會在內部維護的strings pool中通過String的 equels 方法查找是對象池中是否存放有該String對象,如果有,則返回已有的String對象給用戶,而不會在heap中重新創建一個新的String對象;如果對象池中沒有該String對象,jvm則在heap中創建新的String對象,將其引用返回給用戶,同時將該引用添加至strings pool中。注意:使用第一種方法創建對象時,jvm是不會主動把該對象放到strings pool里面的,除非程序調用 String的intern方法??聪旅娴睦樱?
- String str1 = new String("abc"); //jvm 在堆上創建一個String對象
- //jvm 在strings pool中找不到值為“abc”的字符串,因此
- //在堆上創建一個String對象,并將該對象的引用加入至strings pool中
- //此時堆上有兩個String對象
- Stirng str2 = "abc";
- if(str1 == str2){
- System.out.println("str1 == str2");
- }else{
- System.out.println("str1 != str2");
- }
- //打印結果是 str1 != str2,因為它們是堆上兩個不同的對象
- String str3 = "abc";
- //此時,jvm發現strings pool中已有“abc”對象了,因為“abc”equels “abc”
- //因此直接返回str2指向的對象給str3,也就是說str2和str3是指向同一個對象的引用
- if(str2 == str3){
- System.out.println("str2 == str3");
- }else{
- System.out.println("str2 != str3");
- }
- //打印結果為 str2 == str3
再看下面的例子:
- String str1 = new String("abc"); //jvm 在堆上創建一個String對象
- str1 = str1.intern();
- //程序顯式將str1放到strings pool中,intern運行過程是這樣的:首先查看strings pool
- //有沒“abc”對象的引用,沒有,則在堆中新建一個對象,然后將新對象的引用加入至
- //strings pool中。執行完該語句后,str1原來指向的String對象已經成為垃圾對象了,隨時會
- //被GC收集。
- //此時,jvm發現strings pool中已有“abc”對象了,因為“abc”equels “abc”
- //因此直接返回str1指向的對象給str2,也就是說str2和str1引用著同一個對象,
- //此時,堆上的有效對象只有一個。
- Stirng str2 = "abc";
- if(str1 == str2){
- System.out.println("str1 == str2");
- }else{
- System.out.println("str1 != str2");
- }
- //打印結果是 str1 == str2
為什么jvm可以這樣處理String對象呢?就是因為String的非可變性。既然所引用的對象一旦創建就永不更改,那么多個引用共用一個對象時互不影響。
比如Integer是int包裝類、Float是float的包裝類等等。對這些包裝類的值操作實際上都是通過對其對應的基本類型操作而實現的。是不是有 所感悟了?對,String就相當于是char[]的包裝類。包裝類的特質之一就是在對其值進行操作時會體現出其對應的基本類型的性質。在參數傳遞時,包 裝類就是如此體現的。所以,對于String在這種情況下的展現結果的解釋就自然而然得出了。同樣的,Integer、Float等這些包裝類和 String在這種情況下的表現是相同的
所以如下程序輸出 1234
public class Test {
public static void changeStr(String str){
str="welcome";
}
public static void main(String[] args) {
String str="1234";
changeStr(str);
System.out.println(str);
}
}