關於作者的更多博客請訪問
雲裏雲外開源社區
一;不可變字符串String 兩種創建方式
第一種
String handle = new String([string_content]);
Handle句柄,[]表示可寫可不寫。
我先分析一下這段代碼
1、new String;指的是在堆空間中創建一個String類型對象
2、末尾的([string_content]);調用String類的構造方法初始化值爲"string_content"(值隨意)
3、String handle;在棧中聲明一個String類的,名爲"handle"的句柄,注意它不是對象(對象引用)(String類型的句柄只能指向String類型的對象)
4、"="將對象引用指向在堆內存中創建的String類型的對象
基本含義理解後大家再回看這幅圖
例 、創建對象形式
String s= new String(“china”);
先去常量池中找是否有China
若無;則在池中創建一個"china"對象,再去堆中創建一個常量池中的此對象的拷貝對象,再去棧中開闢名爲“s”的空間,存放此對象的鏈接地址。(此時的S,就是句柄)
若有;去堆中創建一個常量池中的此對象的拷貝對象,再去棧中開闢名爲“s”的空間,存放此對象的鏈接地址。
問題1,這段代碼String s= new String(“china”);究竟創建了幾個String對象?它們分別是?
答案;1或2個,分別是(常量池中的China)和堆中的China,若常量池已有China,則爲1
我們繼續
String y= new String(“china”);
這個顯然是成立的,不會報錯,這樣我們就得出。一個對象可以有多個(N個)對象的引用
String y= new String(“ShanXi”);
這樣對象的引用就會重新指向"ShanXi"。
//y句柄改變了指向,指向了常量池中的ShanXi,而china則會成爲虛擬機的垃圾回收機制的對象,在未來的某時被吸收
String y;?在這裏聲明瞭一個對象的引用,但並沒有明確指向,但編譯器不會報錯。
綜上所述,一個對象的引用可以指向1或0個對象。一個對象可以有N個對象的引用
所以也可以這樣表示
String y;
y = new String(“china”);
第二種、直接賦值
2、String d= “china”;
先去常量池中找是否有China
若無;則在池中創建一個"china"對象,再去棧中開闢名爲“d”的空間,存放此對象的鏈接地址。
若有;去棧中開闢名爲“d”的空間,存放此對象的鏈接地址。
問題2,這裏創建了幾個對象呢?
所以第二種方式可能創造0或1個對象
第三個問題
String s = “a” + “b” + “c” + “d” + “e”; 創建了幾個對象呢?
代碼被編譯器在編譯時優化後,相當於直接定義了一個”abcde”的字符串,所以,上面的代碼應該只創建了一個String對象
重要方法intern();
返回字符串對象的規範化表示形式。
用人話說就是獲取對象在常量池中的值,當然它還有更深層次的用法,我也不太會….
利用這個方法可以很好理解字符串特別是常量池的概念
Stringhandle3=newString("TYUT");
Stringhandle4=newString("YunDing");
System.out.println(handle3.intern());
System.out.println(handle4.intern());
答案:
TYUT
YunDing
二、可變字符串StringBuffer
由於我對這個接觸很少,就總結一下構造方法,其他的方法大家可以自行百度
StringBuffer的構造方法:
StringBuffer():無參構造的形式,初始容量爲16
StringBuffer(int capacity):指定容量構造一個字符串緩衝區
StringBuffer(String str):構造一個字符串緩衝區,將指定的字符串內容作爲其初始化內容,長度爲16加上str的長度
例、
StringBuffera=newStringBuffer("abc");
StringBufferb=newStringBuffer();
System.out.println(a.capacity());
System.out.println(b.capacity());
結果分別是19和16
三、(字符串的)比較方法
這一篇先說字符串的,後面再到其他數據類型的比較
兩種比較方式“ == ”和equals()
• “==”;分爲比較基本數據類型和引用數據類型
基本數據類型比較的是值;引用數據類型比較的是內存地址
• equals();這個方法是Object類中的方法,Object是java默認提供的一個類,如果一個類沒有明確指定繼承關係,那麼它將繼承Object,也就是可以使用它規定的方法。
(1)不能比較基本數據類型。
(2)equals()在Object類中是比較對象的內存地址。
public boolean equals(Object obj){
return(this==obj);
}
而在String類中已經將equals()重寫,比較的是對象的值(常量池中的值)
public boolean equals(Object anObject){
if(this == anObject){
return true;
}
if(anObject instanceof String){
String aString = (String) anObject;
if(!COMPACT_STRINGS||this.coder==aString.coder){
return StringLatin1.equals(value,aString.value);
}
}
return false;
}
如果理解了之前的內容,只要你不記混這兩種比較方式,那你應該理解了字符串的比較。給大家一些例子,可以嘗試做一下,後面是輸出結果供對照
//先比較newString();產生的
//內容相同,結果第一個false,第二個顯然true
String handle = newString("ShanXi");
String handle2 = newString("ShanXi");;
System.out.println("handle和handle2相等嗎?"+(handle==handle2));
System.out.println("handle和handle2相等嗎?"+(handle.equals(handle2)));
//內容不同,結果顯然均爲false
String handle3 = newString("TYUT");
String handle4 = newString("YunDing");
System.out.println("handle3和handle4相等嗎?"+(handle3==handle4));
System.out.println("handle3和handle4相等嗎?"+(handle3.equals(handle4)));
//再比較直接賦值型
//內容不同,結果顯然均爲false
String handle5 = "java";
String handle6 = "python";
System.out.println("handle5和handle6相等嗎?"+(handle5==handle6));
System.out.println("handle5和handle6相等嗎?"+(handle5.equals(handle6)));
//內容相同,結果顯然均爲true,因爲兩者都指向同一個內存地址,位於常量池
String handle7 = "java";
String handle8 = "java";
System.out.println("handle7和handle8相等嗎?"+(handle7==handle8));
System.out.println("handle7和handle8相等嗎?"+(handle7.equals(handle8)));
//混合比較
//內容相同,第一個返回false,因爲handle9的地址是在堆中,handle8是在常量池中。第二個返回true
String handle9 = newString("java");
System.out.println("handle9和handle8相等嗎?"+(handle9==handle8));
System.out.println("handle9和handle8相等嗎?"+(handle9.equals(handle8)));
//intern()返回字符串對象的規範化表示形式。通俗一點說,就是返回對應這個字符串內容的那個pool裏的對象
System.out.println("handle9和handle8相等嗎?"+(handle9.equals(handle8.intern())));
//內容不同
String handle10 = newString("js");
System.out.println("handle10和handle8相等嗎?"+(handle10==handle8));
System.out.println("handle10和handle8相等嗎?"+(handle10.equals(handle8)));
• 輸出結果如下:
handle和handle2相等嗎?false
handle和handle2相等嗎?true
handle3和handle4相等嗎?false
handle3和handle4相等嗎?false
handle5和handle6相等嗎?false
handle5和handle6相等嗎?false
handle7和handle8相等嗎?true
handle7和handle8相等嗎?true
handle9和handle8相等嗎?false
handle9和handle8相等嗎?true
handle9和handle8相等嗎?true
handle10和handle8相等嗎?false
handle10和handle8相等嗎?false
最後附上參考鏈接
字符串常量池
字符串拼接內部實現
字符串創建對象面試問題
StringBuffer相關資料