java筆記(2):String(1)

參考資料:網易雲網課地址 數組

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()方法手工入池。

相關文章
相關標籤/搜索