參考資料:網易雲網課地址 數組
http://study.163.com/course/courseMain.htm?courseId=1455026spa
1、String類的兩種實例化方法3d
(1)直接賦值 code
public class Test { public static void main(String arg[]) { String str = "hello world"; System.out.println(str); } }
以上代碼能夠輸出str的值,說明str 已被實例化(未實例化會爲null)。咱們知道String類並非基本數據類型,然而以上代碼並無用new關鍵字開闢內存空間。htm
(2)利用構造方法實例化:對象
其實在String類裏面含有一個構造方法: public String(String str) 在構造裏面依然要接收一個本類對象。blog
public class Test { public static void main(String args[]) { String str = new String("Hello World"); System.out.println(str); } }
說明String類有兩種形式,你們主觀上應該會認爲第二種更加的符合規範,由於通常認爲類都需使用new關鍵字來實例化。但實際來講並非這樣的,具體得往下看。內存
2、字符串的比較開發
基本數值均可用「==」判斷是否相等,String也能夠用「==」進行比較字符串
public class B { public static void main(String[] args) { String stra = "Hello"; String strb = new String("Hello"); String strc = strb;//引用傳遞 System.out.println(stra == strb); System.out.println(stra == strc); System.out.println(strb == strc); } }
輸出結果爲:
false false true
內存圖分析以下:
「==」符號比較的時數據的地址數值,由圖可知,雖然三個變量內容相同,可是地址值並不相同。
若是真要比較地址所指向的內容,可使用String類裏面提供的方法 public boolean equals;
public class B { public static void main(String[] args) { String stra = "Hello"; String strb = new String("Hello"); String strc = strb;//引用傳遞 System.out.println(stra.equals(strb)); System.out.println(stra.equals(strc)); System.out.println(strb.equals(strc)); } }
結果爲
true true true
以上經過equals方法實現了內容的比較,故應當注意在比較字符串時應當使用此方法
一道題目:
請解釋在字符串相等的判斷中「==」與「equals」的區別?
(1)「==」時Java提供的關係運算符,主要功能是進行數值相等判斷,若是用在String對象上,表示的是地址數值的比較;
(2)「equals()」是有String提供的一個方法,此方法專門負責進行字符串內容的比較;
3、字符串常量就是String的匿名對象
實際上任何語言都沒有提供字符串這一律念,不少語言使用字符數組來描述。Java裏也沒有字符串這一基本數據類型,而是經過String類的匿名對象來實現。
例:觀察字符串是匿名對象
public class B { public static void main(String[] args) { String stra = "Hello"; System.out.println("Hello".equals(stra)); } }
匿名對象可以調用方法,故說明字符串爲一個匿名對象
所謂的直接賦值至關於 將一個對象設置了一個名字,但惟一的區別是,String類的匿名對象是由系統自動生成的,並非由用戶直接定義。
開發小技巧:
爲了不出現空指向異常,可將字符串寫在前面調用方法
String input = //由用戶輸入 input。equals("hello")
以上代碼input由用戶輸入賦值,若是用戶沒有輸入則爲空,那麼就會出現空指向異常。
爲了儘可能避免這一狀況發生,可將其倒置
String input = //由用戶輸入 「hello」.equals(input)
4、兩種實例化方式的區別
下面探討String類兩種實例化方式的區別
1.直接賦值
直接賦值就是將一個字符串的匿名對象設置一個名字
String str = "Hello";
此時在內存中會開闢一塊堆內存,而且由一塊棧內存指向該堆內存
咱們接着分析如下代碼:
public class Test { public static void main(String args[] ) { String stra = "hello" ; String strb = "hello" ; String strc = "hello" ; System.out.println(stra == strb) ; System.out.println(stra == strc) ; System.out.println(strb == strc) ; } }
結果爲:
true true true
此時咱們發現,三個比較值都爲真,也就是說三個String對象地址值相等(即三個變量名stra,strb,strc指向同一堆內存,爲同一個對象)。
要想解釋以上結果,需引入共享模式的概念:
在JVM的底層存在有一個對象池(不必定只保存String對象),若是用直接賦值的方式進行String對象的實例化,會將該實例化對象(字符串)入池保存,若是下次繼續使用直接複製方式聲明String對象,而且設置了一樣的內容(字符串值),那麼將直接進行引用,不會開闢新的堆內存空間。(所謂的對象池就是一個對象數組)。
2.構造方法
構造方法即便用new關鍵字
String str = new String("hello");
內存圖分析
能夠發現,若是使用構造方法將會開闢兩塊堆內存空間,而且其中一塊堆內存空間將變成垃圾空間。另外還會對字符串共享產生問題。
public class Test { public static void main(String args[] ) { String stra = new String("hello") ; String strb = "hello" ; System.out.println(stra == strb) ; } }
結果爲
false
若是使用了構造方法其內容並不會保存在內存池之中。
若是但願存入內存池,需手工使用intern()方法
public class Test { public static void main(String args[] ) { String stra = new String("hello") .intern(); String strb = "hello" ; System.out.println(stra == strb) ; } }
結果爲
true
5、總結
String類對象兩種實例化方式的區別:
(1)直接賦值:只會開闢一塊堆內存空間,而且會自動保存在對象池中供下次使用;
(2)構造方法: 會開闢兩塊堆內存空間,一塊將稱爲垃圾,而且將不會自動保存在對象池中,可使用intern()方法手工入池。