Java——String類使用詳解(實例化、字符串比較、匿名對象、兩種實例化方法的區別)

目錄

1、String類的兩種實例化方式

2、字符串比較

3、String匿名對象

4、String類兩種實例化的區別

5、字符串聲明後不可改變

6、結論


1、String類的兩種實例化方式

String類不是一個基本數據類型,它是一個類,這個類設計過程種加入了Java的特殊支持,其實例化形式有兩種形式:

  • 直接賦值: String 對象 = “內容”;
  • 構造方法:public String (String s);

以上兩種方式均可用,但是具體還是有一些區別。

2、字符串比較

對於int類型數據,兩個直接賦值的變量使用“ ==”可以進行想等判斷,但是對於String類型數據卻不能這樣直接比較,見如下範例:

String stra = "hello";
String strb = new String("hello");
String strc = strb; //引用傳遞
System.out.println(stra==strb);  //false
System.out.println(strb==strc);  //true
System.out.println(stra==strc);  //false

以上三個字符串內容一致,但是使用==比較,發現有的比較結果卻是false。實際上這裏的比較 實際上比較的是兩個對象(任意的引用類型)的堆內存的地址數值,屬於數值內容的比較,並非堆內存種保存內容的比較。

若要對兩個字符串進行比較,可以使用String類中的一個方法:public boolean equals(String str)。

String stra = "hello";
String strb = new String("hello");
String strc = strb; //引用傳遞
System.out.println(stra.equals(strb));  //true
System.out.println(strb.equals(strc));  //true
System.out.println(stra.equals(strc));  //true

【經典問題】String 比較中 == 與equals的區別?

  • "=="是關係運算符,可以進行數值比較,如果用在String上,表示對象內存地址數值比較,不能比較內容。
  • equals是String類自己定義的方法,用於進行字符串內容的比較。

3、String匿名對象

任何編程語言都不會提供字符串數據類型,字符串在很多語言中使用字符數組,Java中爲解決這個問題,提供了String類,Java裏面也提供雙引號聲明的數據,這些數據不是普通的變量,而是屬於String類的匿名對象。

【舉例】:驗證匿名對象

String str = "hello";
System.out.printlin("hello".equals(str)); //true

開發中,在比較字符串內容是否相同時,一般將常量寫在前面,這樣避免equals前面的字符串內容爲null,equals方法本身具有null判斷的功能。

4、String類兩種實例化的區別

由第一節中 的內容可知,對於String示例化方式有兩種,到底該使用哪種,兩種的區別是什麼?

1)分析String類對象直接示例化的形式

【直接賦值】使用 的是最多的:

String str = "hello";
System.out.println(str);

開闢一塊堆內存空間,且一塊棧內存直接指向該堆內存空間。

【繼續觀察直接賦值】

String stra = "hello";
String strb = "hello";
String strc = "nihao"; 
System.out.println(stra==strb);  //true
System.out.println(strb==strc);  //false
System.out.println(stra==strc);  //false

很奇怪,是不是和前面分析的不太一樣,其實還是一樣的,只不過有一點需要注意,stra和strb指向的內容是相同的,不會重複開闢堆內存空間。這裏涉及到對象池的概念。

關於對象池(Object Pool):Java設計過程中,爲方便用戶開發,針對幾個特殊的類使用了共享設計的思路,String就屬於其中一個類,這種設計思路是Java自己的支持,只針對於直接賦值的情況。

在使用直接賦值實例化String類對象操作中,字符串內容定義後實際上會自動保存在一個對象池之中,而後,若有其他 的字符串對象也採用直接賦值的形式,且內容與之前的完全相同,則不會開闢新的堆內存空間,而是通過對象池,找到已有的堆內存空間地址,直接引用,所以會出現如上範例的結果。

1)利用構造方法實例化對象

String str = new String("hello");
System.out.println(str);

由以上內存分析可以發現,通過構造方法進行實例化對象操作,最終會產生兩塊堆內存,其中一塊是垃圾空間。

【舉例】:沒有入池的問題

String stra = new String("hello"); //構造方法
String strb = "hello"; //直接賦值
System.out.println(str);//false

使用構造方法進行String類對象實例化,產生的對象不會保存在對象池中,此對象無法重用。若用戶需要讓這個對象入池,只能通過手工入池方法完成:

手工入池:public String intern().

String stra = new String("hello").intern; //構造方法
String strb = "hello"; //直接賦值
System.out.println(str);//此處結果爲true

【經典問題】:String類兩種對象的實例化區別是什麼?

  • 直接賦值(String str ="字符串"):僅開闢一塊堆內存空間,且對象可以自動入池以共其他對象重複使用;
  • 構造方法(String str = new String("字符串")):開闢兩塊堆內存空間,且有一塊會成爲垃圾,產生的對象不會自動入池,需要使用intern()方法手動入池。

5、字符串聲明後不可改變

【舉例】:

String str = "Hello ";
str += "World ";
str = str+ "!!!";
System.out.println(str); //Hello World !!!

 進行內存分析可以發現,以上程序操作都是String類對象的引用發生改變,而字符串的內容實質上根本沒有發生改變,這樣操作形成了很多垃圾空間,因此,在開發中,一定禁止循環修改String。後續會講到StringBuffer和StringBuilder,可以用於循環修改。

6、結論

  • 1)String開發中都使用直接賦值,並且不要頻繁修改,因爲會產生垃圾空間;
  • 2)字符串內容比較時用equals()方法。

 

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