標籤:style blog http color java 資料 2014 問題
Java String類的疑惑:
String是java的常用類之一,本質是字元數組char[]。String類是final類,不可被繼承。關於String的建立,可以通過new來建立對象,也可以直接賦值。但是這兩種建立方式的實現機制是不同的。提到對象的建立,我們就會想到堆、棧,這裡還有一個string pool的概念,JVM維護一個String池,池中的string對象不可重複,string池不屬於堆棧,而是一個常量池。
一、建立
建立一個String對象,主要有兩種方式:
String str1 = new String("abc"); //在string池中建立abc對象,在堆中建立abc對象,棧中的str1指向該對象String str2 = "abc";//在string池中尋找abc對象,已存在,直接將棧中的str2指向該對象仔細看兩行注釋,執行完第一行代碼後,記憶體
執行完第二行代碼,記憶體
可通過記憶體比較來驗證:
先自己思考一下結果再往下繼續啦!
String str1 = "abc";String str2 = "abc";String str3 = new String("abc");System.out.println(str1 == str2); System.out.println(str1 ==str3); System.out.println(str1 == "abc"); System.out.println(str3 =="abc"); System.out.println(str1 == str3.intern());System.out.println(str3 == str3.intern());運行結果:
解析:
==比較的是記憶體位址,
str1==str2;// 都指向string池中的對象,所以返回true
str1==str3;//str1指向string池中的對象,str3指向堆中對象,所以,返回false
str1==“abc”; //都指向string池中的對象,所以返回true
str3==”abc“;//str3指向堆記憶體對象,另一個是string池中的對象,所以,返回false
str1==str3.intern(); //都指向string池中的對象,返回true
str3==str3.intern();//str3指向堆記憶體對象,str3.intern()指向string池中的對象,所以,返回false
intern()方法是返回字串對象的正常化表示形式,也就是說當調用intern()時,如果string池中已經包含一個等於(equals)此string對象的字串,則返回池中的字串。
二、拼接
先來思考一下執行結果:
<span style="white-space:pre"></span>String hello = "hello";String hel = "hel";String lo = "lo";System.out.println(hello == "hel"+"lo");System.out.println(hello == "hel"+"looo");System.out.println(hello== "hel" + lo);
運行結果:
解析:
- 如果+串連的都是常量時,先判斷string池中有沒有hello,如果存在,直接返回其地址,不再重新建立。
- 如果+串連的有物件類型時,則直接在堆中產生一個新對象。
關於String拼接的繼續思考:
由於String類是final的,也就是對象一旦建立,就不能改變其內在狀態了,但是,拼接操作是要改變String的內部狀態的,在這種矛盾下,要維護string的非可變性,只好在拼接完成後再建立一個新的String對象,也就是說,每執行一次拼接操作,都會產生新對象的產生。當大量指向拼接操作時,就會導致大量對象的建立,這樣,就產生了效能問題。
為瞭解決這個問題,jkd為string類提供了一個可變的配套類StringBuffer。由於StringBuffer是可變的,拼接時僅僅是改變了內部資料結構,而不會建立新對象,因此,效能上有很大的提高。