Java – 物件導向 – 基本觀念運用 – String

在單元: 物件導向 – 觀念建立 中最後面提及的物件導向設計觀念, 提及的API的觀念, 可能只是運用類別物件的角色而已. 因此, 在這裡就來介紹使用頻繁度很高的字串(String), 也就是很多單字組合成的串列, 用來表示一句話以上的文字內容資料.

字串String是Java SDK中, 放在 java.lang 的 Package (就是資料夾的概念) 下的類別. 換言之, 就是已經被設計好的類別, 當要使用的時候, 只需要建立出物件之後, 就可以呼叫特定的方法(method) 來運用.

字串物件的產生


最常見的方式就是直接以雙引號來處理字串內容.

String s0 = "Brad Big Company";

此時, 由雙引號刮起來的字串, 就是一個物件實體, 存在記憶體中的特定位址.

  • Brad Big Company : 這串內容, 不包含雙引號的部分, 之後稱之為字串內容.
  • “Brad Big Company” : 這個用一對雙引號刮起來的東西, 之後稱之為字串物件, 也就是存在記憶體中的一個位址.

字串內容, 沒有什麼特別, 就是那一串字. 而”Brad Big Company”就是代表一個字串物件實體, 一個存在記憶體中的一個位址. 而在 System.out.println() 的方法, 詳細的解說, 就是將要顯示的物件, 呼叫其 toString() 方法來呈現出其字串內容. 而字串就是一個物件, 當然就是呼叫 toString() 方法傳回的字串內容來顯示. 而不是直覺上的直接顯示字串內容.

再來查看Java API: java.lang.String 的建構式:

因此, 從宣告為String的物件變數開始, 有以下幾種常見的建構String物件實體方式.

public class StringTest {

  public static void main(String[] args) {
    String s0 = "Brad Big Company";
    String s1 = new String();
    
    byte[] b1 = {97, 98, 99, 100, 101, 102, 103, 104};
    String s2 = new String(b1);	// 透過 byte[] b1陣列來建構出物件實體
    String s3 = new String(b1, 2, 4); // 從 b1 陣列中取出從第2元素開始共4個元素建構
    
    char[] c1 = {'a','b','c','d','e','f','g','h','i'};
    String s4 = new String(c1);	// 透過 char[] c1陣列來建構出物件實體
    String s5 = new String(c1, 2, 4); // 從 c1 陣列中取出從第2元素開始共4個元素建構

    String s6 = new String(s0);
    String s7 = new String("Brad Big Company");
    
  }
}

當然, 還有其他的.

 

字串物件常用方法


字串長度: length()

public class MyStringTest {

  public static void main(String[] args) {
    String test = "0123布萊德大公司abcdefg";	// UTF-8 編碼下的字串內容
    System.out.println(test.length());	// 傳回: 17
    
  }

}

 

取得字串中特定位置的字元: charAt(int)

public class MyStringTest {

  public static void main(String[] args) {
    String test = "0123布萊德大公司abcdefg";	// UTF-8 編碼下的字串內容
    System.out.println(test.length());	// 傳回: 17
    System.out.println(test.charAt(7));	// 傳回: 大
    
  }

}

 

依照上例, 字串長度為17, 位置的編號將會從0開始起算, 一直到16. 如果指定位置大於或是等於17.

public class MyStringTest {

  public static void main(String[] args) {
    String test = "0123布萊德大公司abcdefg";	// UTF-8 編碼下的字串內容
    System.out.println(test.length());	// 傳回: 17
    System.out.println(test.charAt(7));	// 傳回: 大
    System.out.println(test.charAt(17));	// 將出現執行階段的Exception
    
  }

}

就將會拋出例外…

17
大
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 17
  at java.lang.String.charAt(String.java:658)
  at MyStringTest.main(MyStringTest.java:8)

 

字串內容轉成byte[]

public class MyStringTest1 {

  public static void main(String[] args) {
    String test1 = "abcdefg";
    byte[] test1Bytes = test1.getBytes();	// 字串內容轉成 byte[]
    for (byte b : test1Bytes) {
      System.out.println(b);
    }
  }

}

執行結果如下:

97
98
99
100
101
102
103

這個方法很常被使用在文字資料內容與實體檔案進行輸入輸出的處理中, 或是網際網路資料傳遞等應用上.

 

字串內容的特性

String物件實體中, 一個很重要的特性就是當一個String物件實體被產生之後, 字串內容將沒有機會被改變.

String s1 = "Hello, Brad";

s1 的位址會與 “Hello, Brad”物件的位址是一樣的. 該位址所存放的字串內容為Hello, Brad. 但是當,…

s1 = "Hello, World";

此時s1 的位址已經變更了, 不再是剛剛的位址, 而是重新指向到Hello, World字串內容的另一個物件的位址.

所以, 在String中API的所有物件方法, 不會有任何方法是用來改變原來String字串內容.

 

字串添加內容: concat(String)

public class MyStringTest {

  public static void main(String[] args) {
    String test = "0123布萊德大公司abcdefg";	// UTF-8 編碼下的字串內容
    System.out.println(test.length());		// 傳回: 17
    System.out.println(test.charAt(7));		// 傳回: 大
    
    System.out.println(test.concat("OK"));	// 
    
  }

}

執行結果如下:

17
大
0123布萊德大公司abcdefgOK

的確是顯示出後面添加了”OK”. 但是呢, 繼續看下去…

public class MyStringTest {

  public static void main(String[] args) {
    String test = "0123布萊德大公司abcdefg";	// UTF-8 編碼下的字串內容
    System.out.println(test.length());		// 傳回: 17
    System.out.println(test.charAt(7));		// 傳回: 大
    
    System.out.println(test.concat("OK"));
    System.out.println(test);
    
  }

}

執行結果如下:

17
大
0123布萊德大公司abcdefgOK
0123布萊德大公司abcdefg

表示了原來test字串物件變數的字串內容並沒有改變, 那麼, concat() 方法在做什麼事呢?

在將原來 test 字串物件的字串內容, 在其後面添加指定參數字串內容之後, 傳回添加之後的內容的另一個新字串物件實體. 而原字串 test 字串物件實體, 只要沒有變更其指向位址, 字串內容內容絕對不會改變的. 在之後所提及的字串物件方法都是一樣的觀念, 這些方法的重點是在於傳回的是另一個新的字串物件實體.

 

指定字元或是字串在目前字串物件中的位置: indexOf()


這個方法非常實用, 可以當成是在檢查或是確認字串內容中是否存在要檢查的字元或是字串.

  • 如果存在, 則傳回所在的位置 0 ~ (字串長度-1)
  • 如果不存在, 則傳回 -1

在API中有以下四個Overload的indexOf()方法:

public class MyStringTest {

  public static void main(String[] args) {
    String test = "0123布萊德大公司abcdefg";	// UTF-8 編碼下的字串內容
    System.out.println(test.length());		// 傳回: 17
    System.out.println(test.charAt(7));		// 傳回: 大
    
    System.out.println(test.concat("OK"));
    System.out.println(test);
    
    System.out.println(test.indexOf('x'));	// 傳回: -1
    System.out.println(test.indexOf('萊'));	// 傳回: 5
    
  }

}

相對的也提供了, 從後面數起的方法 lastIndexOf()

 

正規表示法比對字串內容: matches()


先來看看以下各列的數字字串, 應該表示什麼樣的資料:

192.168.1.2
2018-01-31
04-22345678
0931-123456
10:21:05

相信都非常容易的判斷出八九不離十的答案.

但是對於程式而言, 該如何以最快最有效率的方式進行判斷比對? 就是透過正規表示法(簡寫: regex). 以一個字串”01234567″來看, 將會以字串物件方法 matched() 的傳回值來判斷.

public class RegexTest {

  public static void main(String[] args) {
    String test1 = "01234567";
    System.out.println(test1.matches("01234567")); 	// 完全一樣
    System.out.println(test1.matches("0...4..7"));	// . 表示任一字元
    System.out.println(test1.matches("0.{7}"));		// . 表示任一字元, 出現7次
    System.out.println(test1.matches("0[0-9]{7}"));	// []表示字元集合出現任一字元, 出現7次
    
  }

}

 

再來看看一個身分證字號的格式:

  • 第一碼: A – Z
  • 第二碼: 1 或是 2, 表示男生或是女生
  • 第三碼之後全部是 0 – 9 之間的數字
  • 全長固定為10碼
public class RegexTest {

  public static void main(String[] args) {
    String test1 = "A123456789";
    System.out.println(test1.matches("[A-Z][12][0-9]{8}"));
    
  }

}

 

 

 

本站資源一切隨緣,
不用註冊, 不看廣告
如果對您有所助益,
歡迎功德隨喜, 金額隨意,
請點擊以下...(感謝您)

功德箱/打賞箱

%d bloggers like this: