2.String有兩種賦值方式(直接賦值和用new開辟空間)
3.String是Java中共享模式的一種應(yīng)用
在這里舉一個例子:
public class Text{
public static void main(String[] args){
String st="abc";
System.out.println("abd".equals(st));
}
}
其中“abc”就是String的匿名對象,String類中的內(nèi)容一旦聲明則不可改變。比如:
public class Text{
public static void main(String[] args){
String str1="abc";
str1+="def";
System.out.println(str1);
}
}
運行結(jié)果為abcdeg,過程如下:String str1="abc",證明棧內(nèi)存中有個str1,在堆內(nèi)存中的內(nèi)容是str1+="def";首先是先有“def”在堆內(nèi)存中開辟空間;然后再進行str1+"def"運算所得的字符串“abcdef”又在堆內(nèi)存開辟一個空間。原來str1所占的堆內(nèi)存空間,現(xiàn)在str1+"def"運算所得的字符又賦給str1,所以str1先斷開指向“abc”的連接,最后就指向“abcdef”新的空間與其建立連接。
雖然以上顯示String的內(nèi)容改變了,但是實際上而言,String改變的只是其內(nèi)存地址的指向,而其本身的內(nèi)容沒有被改變。所以說這樣寫代碼影響程序的性能。
問題:只要是字符串就是一個String匿名對象嗎?
在String類中如果一個字符串已經(jīng)明確了一個對象的指向,則以后其他的String對象如果聲明的內(nèi)容是一樣的,則自動指向同一個空間。
比如:
public class Text{
public static void main(String[] args){
String str1="abc";
String str2="abc";
System.out.println(str1==str2);
}
}
原來的“abc”有沒被引用到,我們知道原來的“abc”已經(jīng)被str1引用, 那么就不可能再生成另外一個“abc”, 只會將原來的“abc”地址指向str2,那現(xiàn)在str1和str2都指向同一個內(nèi)存空間地址,比如“abc”內(nèi)存空間地址為0x1000哈,我們進行System.out.println(str1==str2);
雖然以上顯示String的內(nèi)容改變了,但是實際上而言,String改變的只是其內(nèi)存地址的指向,而其本身的內(nèi)容沒有被改變。所以說這樣寫代碼影響程序的性能。
問題:只要是字符串就是一個String匿名對象嗎?
在String類中如果一個字符串已經(jīng)明確了一個對象的指向,則以后其他的String對象如果聲明的內(nèi)容是一樣的,則自動指向同一個空間。
比如:
public class Text{
public static void main(String[] args){
String str1="abc";
String str2="abc";
System.out.println(str1==str2);
}
}
原來的“abc”有沒被引用到,我們知道原來的“abc”已經(jīng)被str1引用, 那么就不可能再生成另外一個“abc”, 只會將原來的“abc”地址指向str2,那現(xiàn)在str1和str2都指向同一個內(nèi)存空間地址,比如“abc”內(nèi)存空間地址為0x1000哈,我們進行System.out.println(str1==str2);
代碼中進行“==”比較時得到的運算結(jié)果就是true了, 所以說如果內(nèi)存中已經(jīng)有相同內(nèi)容的地址話,我們就不要再開辟新的空間了,如果沒有的話,那我們就要重新聲明開辟新的空間。
在String str1 = new String(“abc”) ;代碼中我們知道“abc”是匿名對象,那么在堆內(nèi)存中就會有塊空間是“abc”,緊接著new String("abc") 使用new在堆內(nèi)存中又開辟了一個空間“abc”,最后String str1 = new String("abc") ;代碼將最后生成的“abc”內(nèi)存地址指向str1,最早的一個“abc”就沒使用上。