String類對象的兩種實例化方法
String并不是一個基本數(shù)據(jù)類型,它本身屬于一個類。但是這個類在設計的過程之中加入了屬于Java的特殊支持,所以對于這個類的對象實例化方式有兩種形式
-
直接賦值:
String 對象名稱 = "內容";
-
構造方法:
String 對象名稱 = new String("內容");
String的相等比較
如果說現(xiàn)在有兩個int型的變量,要進行相等的判斷汽馋,則直接使用“==”即可;如果進行String的比較午笛,我們可先用“=="嘗試:
class StringDemo{
public static void main(String[] args){
String steA = "hello";
String steB = new String("hello") ;
String steC = steB;
System.out.println(steA == steB);//false
System.out.println(steB == steC);//true
System.out.println(steA == steC);//false
}
}
發(fā)現(xiàn)結果并不相等惭蟋,此時我們發(fā)現(xiàn)問題苗桂,字符串的內容實際上都是一樣的药磺,而在使用“==”比較結果是,具體原因如下圖所示:
- 發(fā)現(xiàn)在程序中如果使用“==”比較的只是兩個對象(任意的引用類型)
,并不是對堆內存中保存的內容進行比較
- 如果想要在
String
類中進行比較煤伟,那么可以利用String
類中提供的public boolean equals(String str);
方法進行比較
代碼如下:
class StringDemo{
public static void main(String[] args){
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()"的區(qū)別
- "=="是java的一種關系運算符,可以進行數(shù)值比較便锨,如果用在String上時則是對堆內存地址數(shù)值進行比較围辙,使得結果錯誤
- "equals()"是String類的一個方法,用于進行字符串內容的比較
String匿名對象
任何的編程語言都不會提供有字符串這一數(shù)據(jù)類型放案,字符串的描述在很多語言之中都是用字符數(shù)組表示姚建,而在Java的設計之初為了解決這樣的問題,專門提供了一個String類來進行描述吱殉。但是隨著發(fā)展掸冤,為了能夠讓程序變得更加的易于開發(fā),所以在Java里面也提供雙引號聲明的數(shù)據(jù)友雳,而這些數(shù)據(jù)稿湿,在Java中并不是普通的變量,而是String類的匿名對象
String 字符串對象 = "字符串";
本質:就是為一個字符串的匿名對象起了一個名字
String類兩種實例化對象的區(qū)別(核心)
此時對于String類的聲明方式有兩種押赊,那么這兩種方式到底應該使用哪一種饺藤,以及每種方式的區(qū)別
分析String類對象直接實例化的形式
開辟一塊堆內存空間,并且開辟一塊棧內存空間將直接指向該堆內存
觀察以下代碼:
class StringDemo{
public static void main(String[] args){
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
}
}
內存關系圖如下:
關于對象池的概念(Object Pool):
為了更方便用戶的代碼編寫開發(fā)罗丰,針對于幾個特殊的類使用了共享設計的思路,其中String類屬于這其中的一員咽袜。這種設計思路是Java自己的支持丸卷,而且只針對于直接賦值的情況
在使用直接賦值實例化String類對象的操作之中,字符串的內容定義之后實際上會自動將其保存在一個對象池之中询刹,而后如果現(xiàn)在有其他的字符串對象也采用了直接賦值的形式谜嫉,并且內容與之前的字符串內容完全相同,那么不會開辟新的堆內存空間凹联,而是會通過對象池找到已有的堆內存空間地址沐兰,直接引用即可
回到上方的疑問:由于對象池的存在,當若干個字符內容相同時蔽挠,地址是完全相同的住闯,所以“==“的結果也是相同的,這樣的設計就是共享設計模式
分析String類利用構造方法實例化對象的形式
代碼如下:
class StringDemo{
public static void main(String[] args){
String str = new String("hello");
System.out.println(str);
}
}
內存關系圖如下:
分析以上情況:
通過此時的內存分析可以發(fā)現(xiàn)澳淑,如果采用了構造方法進行String類對象的實例化操作比原,那么最終會產生兩塊堆內存,其中一塊是垃圾空間
如果使用了構造方法進行String類對象實例化杠巡,那么所產生的的對象將不會保存在對象池之中(此對象無法重用)量窘,如果用戶需要其入池,只能通過
public String intern();
手工入池
面試題:請解釋String類兩種對象實例化的區(qū)別
直接賦值
String str = "字符串";
:只會開辟一塊堆內存氢拥,且對象可以自動入池以供重復使用構造方法
String str = new String("字符串");
:會開辟兩塊堆內存蚌铜,且其中一塊為垃圾空間,由構造方法聲明的實例化對象不能自動入池嫩海,需要調用intern()
方法手動入池
字符串一旦聲明不可改變
觀察以下代碼:
class StringDemo{
public static void main(String[] args){
String str = "hello ";
str += "world";
str += "!!!";
System.out.println(str);
}
}
分析內存關系:
可以發(fā)現(xiàn)整個的操作流程之中冬殃,都是String類對象的引用發(fā)生著改變,而字符串本身的內容并沒有改變叁怪,這樣的操作會產生大量垃圾审葬,因此杜絕使用
總結
String類開發(fā)中都使用直接賦值,并且不要頻繁修改
字符串內容比較時使用
equals()
方法