java數據類型淺析之字符串(二)

Java字符串.png

關於作者的更多博客請訪問

雲裏雲外開源社區

一;不可變字符串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類型的對象

基本含義理解後大家再回看這幅圖
內存圖解.png
例 、創建對象形式
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相關資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章