2013年9月3日 星期二

String StringBuilder StringBuffer

文字運算相關類別
作者:許裕永
Java程式的撰寫,在學會了基礎語法後,就要開始學習如何使用Java提供的類別,來協助我們作資料的運算。 在陣列中,我們學會了如何儲存大量的資料。但是要運算資料,卻還是得靠設計師撰寫程式碼。為了簡化設計師的工作,Java提供相當多的類別(還在持續的增加),依其功能性的不同,分別置於不同的package之中(請參閱JDK說明文件)。
char〔〕 a={‘J’,‘a’,‘v’,‘a’}; 此敍述句宣告並指派了一個字元陣列,其值為‘J’,‘a’,‘v’,‘a’四個字元。如果現在要把這四個字元轉換為大寫字母,設計師便必須寫一個迴圈,迴 圈中依序取得每一個陣列元素,判斷它是否為小寫字母。如果是:則將該字母減去32,來轉換為大寫字母。雖然程式碼並不複雜,但是如果能把這些常用的運算, 事先寫好。然後設計師便可以用「呼叫」的方式,來執行這些功能,自然就簡化了程式設計師的工作。甚至,部份複雜的運算,設計師也沒有必要了解其運算的方 式。只要記得「呼叫」某一個「方法」,便能執行該項運算,這樣更可以讓設計師致力於程式碼的撰寫,而不必去涉獵其他與程式語言無關的學問。例如:設計師不 必了解開根號的運算要怎麼寫,只要知道有一個Math的類別,提供一個sqrt的方法,可以執行開根號的運算就可以了(後續章節中介紹)。 本章除了介紹各種與字串相關的類別,更探討了關於物件及實體方法成員的關係以及方法呼叫的基本觀念,讓大家在熟讀本章後,能夠建立好物件導向的基本概念: 「類別建構物件、物件執行方法」。 另外,從本章開始,書中所介紹的類別及界面,都只能夠讓讀者對該類別或界面有基本認識,請讀者一定要搭配JDK說明文件,逕行參考。
1.String
1-1 物件建立
String 參考變數=new String(參數);
String 參考變數=”字串”;
宣告敍述中的「String 參考變數」,指的是:「以類別名稱 String為型別,宣告一個參考變數」。而指派敍述中的「new String(參數)」,指的是:「呼叫類別String的建構方法 (Constructor),來建構一個物件,並把該物件的物件代號指派給參考變數」。
用建構方法來建構物件,是Java中所有類別建構物件時,通用的建 構方式。也就是說:每個可以用new建構成物件的類別,都會提供一個或一個以上的建構方法,每個建構方法所須要的參數都不同,可以讓設計師依實際需求呼 叫。 在JDK文件中,String類別的建構方法摘要(Constructor Summary)中,便列出了13個建構方法。這樣設計師便可以依照所擁有的 資料來源,來呼叫適當的建構方法。例如:程式中讀取了一個文字檔,而得到了一個100個長度的字元陣列,便可以用該字元陣列為參數來呼叫 String(char〔〕 value)這個建構方法,來建構String物件。或者設計師依照了某一段文字的編碼方式,得到一個byte型別的陣列, 此時便可以呼叫String(byte〔〕 value)這個建構方法,來建構String物件。 當然,因為學會的類別還不夠多,上述的兩種狀況目前還做不出來,我們將在後續章節中再介紹。在這裏,主要是要讓大家了解,建構方法所扮演的角色:「它是讓 設計師用來建構某一個類別的物件時,所呼叫的方法」。
例一:
  byte[] byteValue={74,97,118,97};
  char[] charValue={'J','a','v','a'};
  
  //呼叫以byte陣列為參數的建構方法
  String a=new String(byteValue);

  //呼叫以char陣列為參數的建構方法
  String b=new String(charValue);

  //呼叫以字串值為參數的建構方法
  String c=new String("Java");

  System.out.println(a);
  System.out.println(b);
  System.out.println(c);

例二:
  String a="Java";
  System.out.println(a);
在此例中,直接把字串值置於指派運算符號右側,也可以建構String物件。
例三:
 String a=”java”;
 a=”Java”;
 System.out.println(a);
第二行敍述句,並不是把原先字串值“java”改成“Java”。而是另外建構一個字串值為“Java”的String物件,再把這個新String物件的物件代號,指派給參考變數a。
至於兩種建構方式所建構的String物件,使用上並沒有什麼差異性。只是在記憶體的配置上不一樣,關於這一點將於第三節中討論。
1-2 常用方法
String類別所建構的物件,有一個特色:「物件的值,不可以變更」。也就是說:「String物件一旦建構完成,無論呼叫什麼方法,均不會改變原String物件的值,而是建構一個新的String物件」。 物件可以呼叫類別中所宣告的方法,來執行預設的運算。但要先了解方法的名稱、呼叫所須要的參數及運算結果的資料型別。
位於方法名稱前端的資料型別宣告,代表這個方法執行結果的型別。若 此型別為基本資料型別,代表方法的運算結果是一個該型別的值(例:int length())。若型別為類別名稱,則代表方法執行的結果為該類別所建構的 物件(例:String toUpperCase())。運算的結果可以指派給變數(例:int b=a‧length()),也可以置於運算式中再運算 (例:int b=(a‧length())+5*6;)。
參數宣告了本方法被呼叫運算時,一定需要的值(基本資料型別)或物件(類別)。也就是呼叫方法時,必須在呼叫敍述中給予該方法指定的參數值,該方法才能正確的運算(例:a‧charAt(0))。 而方法的呼叫可以用參考變數代表物件呼叫(例:a‧legth()),也可以用物件直接呼叫(例:new String(“Java”)‧length()或“Java”‧length() 。
方法一:byte〔〕 getBytes()
方法名稱:為getBytes。
參數:不需要。
運算結果:取得物件中每一個字元的字元碼,並建立成一個byte〔〕型別的陣列物件。
例一:
  String s=new String("Java SCJP 5.0");
  byte[] a=s.getBytes();
  for(byte b:a){
   System.out.print((char)b + " ");
   System.out.println(b);
  }
參考變數s代表一個物件,那個物件的值是“Java SCJP  5‧0”,這個物件以getBytes方法運算的結果是一個byte〔〕型別的陣列物件,再用迴圈將陣列元素逐一列印。請注意,執行方法的是物件,不是參 考變數,參考變數只是一個讓程式設計師用來控制物件的代號。
例二:
  String s=new String("Java SCJP 5.0");
  for(byte b:s.getBytes()){
   System.out.print((char)b + " ");
   System.out.println(b);
  }
s‧getBytes()這個敍述句,本身就代表它運算的結果。如果只運算一次,並不一定要把運算結果指派給另一個變數。
例三:
  for(byte b:"Java SCJP 5.0".getBytes()){
   System.out.print((char)b + " ");
   System.out.println(b);
  }
字串值本身就是一個String物件,如果只運算一次,不一定要指派給參考變數。再一次注意:執行方法的是物件,不是參考變數。
方法二:char charAt(int index)
參數:呼叫此方法時,必須給一個int資料型別的值。這個參數可以是一個整數值、一個int變數或運算式。index的意思並不是說變數名稱要命名為index,它只是提示這個參數在本方法執行過程中,所扮演的角色。 運算結果:取得String物件中,序號值為該參數值的字元。(序號從0開始)
例一:
  Scanner s=new Scanner(System.in);

  System.out.print("請輸入任意字串->");
  String sample=s.next();
  System.out.println("字首為:" + sample.charAt(0));
小括號中輸入欲取得字元的序號,0代表物件的第一個字元。

例二:
  Scanner s=new Scanner(System.in);

  System.out.print("請輸入任意字串->");
  String sample=s.next();
  System.out.print("請輸入欲顯示之字元序號-->");
  int i=s.nextInt();

  System.out.println("第" + (i+1) +"個字元為:" + sample.charAt(i));
小括號中輸入一個int資料型別的變數。

方法三:int length()
運算結果:取得String物件的長度。要注意的是:這是String物件的方法,和取得陣列物件長度的指令length是不一樣的。方法名稱後面要加小括號,指令不用。
例一:
  Scanner s=new Scanner(System.in);

  System.out.print("請輸入任意字串->");
  String sample=s.next();
  int upper=0,lower=0,number=0,other=0;

  for(int a=0;a<sample.length();a++){
   char c=sample.charAt(a);
   if(c>='A' && c<='Z')
    upper++;
   else if(c>='a' && c<='z')
    lower++;
   else if(c>='0' && c<='9')
    number++;
   else
    other++;
  }

  System.out.println("大寫英文字母共有" + upper + "個");
  System.out.println("小寫英文字母共有" + lower + "個");
  System.out.println("數字字元共有" + number + "個");
  System.out.println("其他符號共有" + other + "個");
迴圈宣告的記數值a會從0執行到(物件的長度-1),迴圈中則逐一取得String物件的每一個字元,判斷並統計其樣式之後列印。
方法四:String concat(String str)
參數:呼叫此方法時,必須給一個String物件當參數。
運算結果:將執行此方法的String物件的值,串聯當參數的String物件的值,建構成一個新的String物件。
例一:
  String a="Java";
  String b="5.0";
  String c=a.concat(b);
  System.out.println(a);
  System.out.println(b);
  System.out.println(c);
請注意本例中,a與b的值並沒有改變。

例二:
  String a="Java";
  String b="5.0";
  a=a.concat(b);
  System.out.println(a);
  System.out.println(b);
請注意本例中,a的值已改變。因為參考變數a中所儲存的物件代號,已經被指派為,串聯後的新String物件的物件代號了。
方法五:String replace(char oldChar, char newChar) 
參數:呼叫此方法時,必須給兩個char型別的值做參數。 運算結果:依照執行此方法的String物件的值,建構一個新的String物件,並將其中符合第一個參數的字元,轉換為第二個參數的字元。
例一:
  String a="JAVA";
  a=a.replace('A','a');
  System.out.println(a); 
輸出的結果是:JaVa。請注意:因為這個方法的呼叫敍述,置於指派運算符號(“=”)右側,代表要把運算結果指派給“=”左側之參考變數a,所以參考變數a所代表的物件,已變更為replace這個方法新建構的String物件。
方法六:String[] split(String regex) 
運算結果:將執行此方法的String物件的值,以String參數regex為分界進行分割,並將分割的結果,建構成String物件的一維陣列。
例一:
  String a="屏東,高雄,台南,台中,台北";
  String[] b=a.split(",");
  for(String c:b){
   System.out.println(c);
  }
請注意:a的值並沒有改變。

方法七:String substring(int beginIndex, int endIndex) 
運算結果:截取執行此方法的String物件的值中,從第一個參數至第二個參數的前一個字元之間的值,來建構一個新String物件。
例一:
  String a="0123456789";
  String b=a.substring(1,5);
  System.out.println(b);
輸出結果:1234。請注意:是第二個參數的前一個字元。

方法八:int indexOf(String str)
運算結果:String參數str於執行此方法的String物件的值中,第一次出現的位置(以序號表示)。
例一:
  String a="0123456789";
  int b=a.indexOf("5");
  System.out.println(b);
輸出結果:5。

方法九:String toUpperCase() 運算結果:依照執行此方法的String物件的值,建構一個新的String物件,並將所有字元全部改為大寫字元。
方法十:String toLowerCase()  
運算結果:依照執行此方法的String物件的值,建構一個新的String物件,並將所有字元全部改為小寫字元。
本章是第一次為讀者介紹方法的呼叫,所以用了比較多的範例,來讓大家了解方法呼叫時,參數的傳遞及運算結果的應用。初學者應多加練習。進階者應自行參閱JDK說明文件,測試其他方法,以期能對物件做更多的運算。
1-3 物件的記憶體配置
字串的運算在大部份的程式中,都扮演著十分重要的角色。而且重複使 用的機率也最大。假設有一支會員管理程式,執行時會讀入所有會員的資料,其中有一個字串陣列物件,記錄著所有會員的居住城市,那這些城市名稱會不會重複, 當然會。也就是字串陣列物件中,有相當多的值是重複的。也就是說:「記憶體中儲存著大量重複的字串值」。 為了更有效率的管理字串值使用的記憶體,Java特別規劃了String constant pool的管理機制。這是Java特別規劃的記憶體範圍,這 個範圍中的字串值,不會重複建構,但可以讓不同的參考變數共同使用。 當Java在程式碼中遇到用雙引號包含的字串值時(例:“Java”),便會立刻在這個範圍中以該字串值建構一個String物件(但若此值的物件已存 在,則不會重複建構)。當有另一個參考變數的指派值和範圍中的值相同時,便會把範圍中已經存在的這個String物件的物件代號指派給它。也就是說: 「String constant pool中的String物件,可以讓任意個以相同字串值直接指派的參考變數共用」。
在前面提到過,String物件建構的方式有兩種,兩種方式建構的 String物件使用上並沒有什麼差異性,但在記憶體的配置上就完全不一樣了。String物件建構時,如果是用new呼叫建構方法,那麼無論要建構的 String物件,String cnostant pool中是否已經存在,Java均會在一般的記憶體中,建構一個String物件。只不過,若 String constant pool中沒有目前要建構的String物件,那Java會另外建立一個一模一樣的String物件置於String  constant pool之中。
如果是用字串值直接指派的方式,而且指派的字串值String  constant pool中已經存在,Java便會將已經存在的String物件的物件代號,指派給參考變數,而不會再建構新的String物件。但 是,如果指派的字串值String constant pool中不存在,Java便只會在String constant pool中建構一個新的 String物件,再指派其物件代號給參考變數。而不會建構於一般的記憶體。
例一:
 String a=”Java”;
 String b=”Java”;
例中的參考變數a,所代表的String物件會建構於String  constant pool之中,當參考變數b的String物件要建構時,因為String constant pool中已經有一個String物 件“Java”,所以Java便不會再建構新的String物件,而是將已經存在的String物件的物件代號指派給參考變數b。所以a和b是指向同一個 String物件。也就是說,本例雖然有兩行宣告及建構String物件的敍述句,但其實只建構一個String物件。
例二:
 String a=new String(“Java”);
 String b=”Java”;
例中的參考變數a,除了在一般記憶體中建構了一個String物 件,也在String constant pool中建構了一個一模一樣的String物件。而參考變數b,Java便不會再建構String物件,而是 將String constant pool中的String物件的物件代號指派給它。本例共建立了兩個String物件。
例三:
 String a=new String(“Java”);
 String b=new String(“Java”);
例中的參考變數a,除了在一般記憶體中建構了一個String物 件,也在String constant pool中建構了一個一模一樣的String物件。而參考變數b,也用new呼叫建構方法,Java一樣會在一 般記憶體中建構一個String物件。但是因為String constant pool中已經有一模一樣的String物件存在,所以String  constant pool中便不會再建構。本例共建立了三個String物件。
了解String物件的記憶體配置後,設計師在撰寫程式碼時,便可 以依照實務上的需要,來選擇適當的String物件建構方式。並不是用new就比較好,也不是用直接指派就比較方便。而是若要指派的字串值其重複性高,用 值接指派的方式,比較節省記憶體空間,運算效率也比較好。但是若變動性高的字串值,用new就會比較合適。
1-4 String物件比對
在學習陣列時,我們有學到陣列的比對有分為:「參考變數的比對及陣列物件的比對」。其實應該說,所有物件都一樣,因為參考變數中儲存的是某一物件的物件代號,所以用關係運算符號的“==”比對兩個參考變數時,是在比對這兩個參考變數是否代表同一個物件。
例一:
  String a=new String("Java");
  String b=new String("Java");
  String c=a;
  System.out.println(a==b);
  System.out.println(a==c);
參考變數a及參考變數b,分別表不同的String物件。雖然 String物件的字串值完全一樣,但a及b所儲存的物件代號並不一樣,所以運算a==b的值為false。而c=a的意思,是把a所儲存的物件代號,複 製後指派給參考變數c,所以a和c中所儲存的物件代號是一樣的,運算a==c的結果自然是true。
例二:
  String a=new String("Java");
  String b="Java";
  String c="Java";
  System.out.println(a==b);
  System.out.println(b==c);
此例要特別注意String物件的記憶體配置狀況。參考變數a的 String物件會建立兩個,一個位於一般記憶體,一個位於String constant pool。參考變數a所儲存的是一般記憶體的String物 件的物件代號。而參考變數b及c,其宣告及指派敍述句執行時,String constant pool中已經存在了一個字串值為“Java”的 String物件,Java便不會再建構新的String物件,而是把String constant pool中,字串值為“Java”的String 物件的物件代號,指派給b及c。此例執行結果為:false true。
若要比對的是物件的內容,則必須呼叫String類別中所提供的方法。
方法:boolean equals(Object o)
參數:呼叫此方法時必須提供一個任意類別建構的物件為參數。
運算結果:執行此方法的String物件的值和參數物件的值的比對結果。若兩個物件的值完全一樣,則運算結果為true;否則運算結果為false。
例一:
  String a=new String("Java");
  String b=new String("Java");
  String c="Java";
  System.out.println(a.equals(b));
  System.out.println(b.equals(c));
本例中三個參考變數的代表的String物件的字串值均為“Java”,所以無論它們是否指向同一個String物件,用equals比對的結果都是true。
範例:身份證字號檢測程式。
合法身份證規則:
共十個字元。
第一個字元必須是大寫英文字母。
第二個字元必須是‘1’或‘2’。
第三個字元至第十個字元必須是數字字元。
第一個英文字元依照下方英文字母數字代號表來格取得數字代號。
用數字代號取代原英文字母,得到一個11位數之數字。
將11位數的數字拆開成11個個位數的數字,並分別乘以
1,9,8,7,6,5,4,3,2,1,1。
將步驟7得到的11個數字相加。
若步驟8得到數字是10的倍數即為正確的身份證字號
英文字母數字代號表
英文字母
數字代號
10
11
12
13
14
15
16
17
18
19
英文字母
數字代號
20
21
22
23
24
25
26
27
28
29
英文字母
數字代號
30
31
32
33
34
35
PS 請注意順序並非完全依照英文字母順序。




2. StringBuffer
用String類別建構的String物件,其物件內容無法變更。 即使只是改變其中一個字元的大小寫,或增加減少一個字元,其執行結果都是建構一個新的String物件後重新指派。針對變動性不大的字串值而言,這種特性 可以增加執行效率,但是如果是變動性較大的字串值,其效率便反而變差了。 Java提供了其他可以建構運算字串值的物件的類別,StringBuffer便是其中之一,這個類別所建構的物件的字串值是可以變更的。也就是說:「這 個類別所建構的物件的內容可以任意修改,而不必再建構新的物件,其字串值也不會在String constant pool中建構成物件」。 例如程式碼中要讀入一個文字檔,並修改其中部份內容後再儲存。這種狀況下,因為讀入的檔案文字適必佔用的大量的記憶體空間,若將這些文字建構成 String類別的物件,進行修改時,每次修改都要再建構一個新的String物件,那麼整支程式的執行不但耗用過量的記憶體空間,也拖慢了執行的速度。 這種狀況,就比較適合把檔案內容建立成StringBuffer類別的物件。
2-1 StringBuffer物件建立
StringBuffer 參考變數=new StringBuffer();
String Buffer 參考變數=new StringBuffer(int capacity);
String Buffer 參考變數=new StringBuffer(String str);
StringBuffer顧名思義就是具有緩衝功能的類別,所以它 建構的物件就能夠隨時變更字串值的長度或內容。StringBuffer的建構方法共有四個(請參閱JDK文件中StringBuffer類別中的 Constructor Summary表格)。這裡列出比較常用的三個。
第一個建構方法所建構的物件,其字串值是空的,但是Java會配置16個字元(32Byte)的空間給這個物件。 第二個建構方法所建構的物件,其字串值也是空的,而Java會依照參數所指定的大小來配置記憶體空間。 第三個建構方法則是以String類別的物件為參數,來建構StringBuffer類別的物件。請注意:「用雙引號包含的字串值,視為String類別的物件,如:“Java”」。
例一:
 Scanner s=new Scanner(System.in);
  StringBuffer a=new StringBuffer();
  StringBuffer b=new StringBuffer(30);
  StringBuffer c=new StringBuffer("Java");
  System.out.print("請輸入任意字串-->");
  StringBuffer d=new StringBuffer(s.next());

  System.out.println(a.length());
  System.out.println(b.length());
  System.out.println(c.length());
  System.out.println(d.length());
參考變數a及b,建構時Java有配置記憶體空間給物件,但其字串值仍是空的,所以字串長度為0。參考變數d必須注意,s‧next()所讀入的,是String類別的物件,必須放在建構方法之中做參數,不可以寫成“StringBuffer d=s‧next();”。 2-2 常用方法
本類別中修改物件內容的方法,均有宣告運算結果為 StringBuffer,但這並不表示說修改後的內容會建構成新的StringBuffer物件。運算結果代表的還是執行這個方法的物件。這只是方便設 計師有必要時,在變更物件內容後,可以把物件代號指派給其他的參考變數,並不是建構了新的StringBuffer物件。
方法一:StringBuffer append(參數)
運算結果:將參數轉換為字串值並串聯於原字串值之後。
例一:
  StringBuffer a=new StringBuffer("Java");
  a.append(5);
  a.append('.');
  a.append("0");
  System.out.println(a);
無論參數為任意基本資料型別的資料或String類別的物件,均可轉換為字串值並串聯於物件字串值的末端。
例二:
  StringBuffer a=new StringBuffer("Java");
  StringBuffer b=a.append("5.0");
  
  System.out.println(a);
  System.out.println(b);
  System.out.println(a==b);
此例中,參數變數a及b代表同一個物件,其字串值為“Java5‧0”。
方法二:StringBuffer delete(int start, int end)
運算結果:刪除物件中,從序號start開始至end前一個字元之內容。
例一:
 StringBuffer a=new StringBuffer("0123456789");
 a.delete(1,5);
 System.out.println(a);
列印“056789”。

方法三:StringBuffer insert(int offset,參數)
運算結果:將參數轉換為字串後,插入於offset之序號位置。
例一:
  StringBuffer a=new StringBuffer("Java 5.0");
  a.insert(5,"SCJP ");
  System.out.println(a);
列印”Java 5.0 SCJP”。

方法四:String toString()
運算結果:以物件的字串值,另外建構一個String類別之物件。
部份與Strnig類別相同之方法並末列出,請自行參閱JDK說明文件。
2-3 StringBuffer物件比對
在上一節中曾討論到,關於String物件的比對可以分為物件代號 的比對(用“==”)及字串值的比對(呼叫equals(物件))。但那是針對String類別所建構的物件而言。在Java中除了少部份特定類別之外 (後續章節介紹),大部份的類別的equals(參數)的執行結果是和“==”一樣的。
例一:
  StringBuffer a=new StringBuffer("Java");
  StringBuffer b=new StringBuffer("Java");
  System.out.println(a==b);
  System.out.println(a.equals(b));
兩種比對模式的值都是false。

例二:
  StringBuffer a=new StringBuffer("Java");
  StringBuffer b=new StringBuffer("Java");
  System.out.println(a==b);
System.out.println(a.toString().equals(b.toString()));
若要比對兩個StringBuffer物件的值,必須以之建構 String物件後,再用equals來比對。 a.toString().equals(b.toString())這種寫法,讀者是第一次看到,卻是Java中常用的寫法。a‧toString() 建構了一個匿名的String物件,這個匿名的String物件呼叫equals方法來比對b‧toString()建構的匿名物件。
3. StringBuilder
在Java 5‧0中為了增加字串運算的效率,新增了一個字串相關 類別,叫StringBuilder。這個類別的建構方法,成員方法及運算方式和StringBuffer完全一樣。唯一的差別是沒有執行緒安全的機制 (後續章節介紹)。 StringBuffer類別中的所有方法,均有設計執行緒安全的機制,而也因為這樣,執行的效率便打了折扣。若設計師認為目前所寫的程式沒有執行緒安全 的顧慮時,使用StringBuilder類別來建構運算字串值的物件,可以增加程式執行效率。
4. 認證重點整理
4-1 String
  • 用建構方法來建構物件,是Java中所有類別建構物件時,通用的建構方式。
  • 建構方法所扮演的角色:它是讓設計師用來建構某一個類別的物件時,所呼叫的方法。
  • Java在程式碼中遇到用雙引號包的字串值時,便會自動依此字串值建構一個String類別的物件。
  • 位於方法名稱前端的資料型別宣告,代表這個方法的執行結果的型別。
  • 若此型別為基本資料型別,代表方法的運算結果是一個該型別的值。
  • 若型別為類別名稱,則代表方法執行的結果為該類別所建構的物件。
  • 參數宣告了本方法被呼叫運算時,一定需要的值或物件。
  • 方法的呼叫可以用參考變數代表物件呼叫,也可以用物件直接呼叫。
  • 物件建構時,如果是用new呼叫建構方法,那麼無論要建構的物件,String cnostant pool中是否已經存在,Java會均在一般的記憶體中,建構一個物件。
  • 只不過,若String constant pool中沒有要建構的物件,那Java會另外建立一個一模一樣的物件置於String constant pool之中。 如果是用字串值直接指派的方式,而且指派的物件String constant pool中已經存在,Java便會將已經存在的物件的物件代號,指派給參考變數,而不會再建構新的物件。
  • 但是,如果指派的字串值String constant pool中不存在,Java便只會在String constant pool中建構一個新的物件後指派其物件代號。而不會建構於一般的記憶體。
  • 用關係運算符號的“==”比對兩個參考變數時,是在比對這兩個參考變數是否代表同一個物件。
  •  若要比對的是物件的內容,則必須呼叫String類別中所提供的方法:equals(Object o)。
  • 類別中宣告的所有方法成員,以運算的對象來區分,可以分為實體方法成員(instance member)及類別方法成員(class member)。
  • 類別方法成員的運算和物件無關,所以也可以不必用物件(參考變數)來呼叫,可以用類別名稱直接呼叫。
  • 即使程式中並無該類別所建構的物件,一樣可以用類別名稱來呼叫該類別的類別方法成員。
4-2 StringBuffer
  • StringBuffer類別所建構的物件是可以變更的。也就是說,這個類別所建構的物件的內容可以任意修改,而不必再建構新的物件,其字串值也不會在String constant pool中建構物件。
  • StringBuffer類別中修改物件內容的方法,均有宣告運算結果為StringBuffer物件,這並不表示說修改後的內容也有建構成新的StringBuffer物件。它代表的還是原物件。 若要比對兩個StringBuffer物件的值,必須以之建構String物件後,再用equals來比對。
4-3 StringBuilder StringBuffer
  • 類別中的所有方法,均有設計執行緒安全的機制,而也因為這樣,執行的效率便打了折扣。若設計師認為目前所寫的程式沒有執行緒安全的顧慮時,使用StringBuilder類別來建構物件,可以增加程式執行效率。

沒有留言:

張貼留言

注意:只有此網誌的成員可以留言。