String str=new String("abc");創建了幾個String對象?


String str=new String("abc");

 

我們可以把上面這行代碼分成String str、=、"abc"和new String()四部分來看待。String str只是定義了一個名為str的String類型的變量,因此它並沒有創建對象;=是對變量str進行初始化,將某個對象的引用(或者叫句柄)賦值給 它,顯然也沒有創建對象;現在只剩下new String("abc")了。那么,new String("abc")為什么又能被看成"abc"和new String()呢?我們來看一下被我們調用了的String的構造器:

  Java代碼

 

  public String(String original) {
  //other code ...
  }

  大家都知道,我們常用的創建一個類的實例(對象)的方法有以下兩種:

  • 使用new創建對象。
  • 調用Class類的newInstance方法,利用反射機制創建對象。

  我們正是使用new調用了String類的上面那個構造器方法創建了一個對象,並將它的引用賦值給了str變量。同時我們注意到,被調用的構造 器方法接受的參數也是一個String對象,這個對象正是"abc"。由此我們又要引入另外一種創建String對象的方式的討論——引號內包含文本。

  這種方式是String特有的,並且它與new的方式存在很大區別。

  Java代碼

  String str="abc";

  毫無疑問,這行代碼創建了一個String對象。

Java代碼

  String a="abc";

  String b="abc";

  那這里呢?答案還是一個。

  Java代碼

  String a="ab"+"cd";

  再看看這里呢?答案是三個。有點奇怪嗎?說到這里,我們就需要引入對字符串池相關知識的回顧了。

  在JAVA虛擬機(JVM)中存在着一個字符串池,其中保存着很多String對象,並且可以被共享使用,因此它提高了效率。由於String 類是final的,它的值一經創建就不可改變,因此我們不用擔心String對象共享而帶來程序的混亂。字符串池由String類維護,我們可以調用 intern()方法來訪問字符串池。

  我們再回頭看看String a="abc";,這行代碼被執行的時候,JAVA虛擬機首先在字符串池中查找是否已經存在了值為"abc"的這么一個對象,它的判斷依據是String 類equals(Object obj)方法的返回值。如果有,則不再創建新的對象,直接返回已存在對象的引用;如果沒有,則先創建這個對象,然后把它加入到字符串池中,再將它的引用返 回。因此,我們不難理解前面三個例子中頭兩個例子為什么是這個答案了。

  對於第三個例子:

  Java代碼

  String a="ab"+"cd";

  "ab"和"cd"分別創建了一個對象,它們經過“+”連接后又創建了一個對象"abcd",因此一共三個,並且它們都被保存在字符串池里了。

  現在問題又來了,是不是所有經過“+”連接后得到的字符串都會被添加到字符串池中呢?我們都知道“==”可以用來比較兩個變量,它有以下兩種情況:

  如果比較的是兩個基本類型(char,byte,short,int,long,float,double,boolean),則是判斷它們的值是否相等。

  如果表較的是兩個對象變量,則是判斷它們的引用是否指向同一個對象


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM