---
# System prepended metadata

title: Java - String Class
tags: [Java, Basic Java]

---

# Java - String Class
###### tags: `Java` `Basic Java`

## 幾個重點：
1. 歸在java.lang的package當中，使用時不需要import可以直接用
2. 所有""所宣告的String都是此類別的物件
3. **String is immutable.** 物件實例化後都是不能改變的，我們只能做到改變reference(也就是改變指向的String物件)


## 常用constructor
1. String str = new String(char[] chars);
2. String str = new String(byte[] bytes);


## StringTable的概念
1. 沒有相同的字串：就會在string table中創建一個新的地址指向該字串
2. 若有相同的字串：就會直接將一樣字串的地址賦值給變數
3. stringtable存在heap當中
4. 實例化的(new)字串不會在string table中，而是在heap中

說明：
```
        String str1 = "abc";
        String str2 = "abc";
        System.out.println(str1 == str2);
```
結果會是true，因為兩參數都指向string table中同一個字串的地址，節省memory space

延伸題：
```      
        String str1 = new String("abc");
        String str2 = new String("abc");
        System.out.println(str1 == str2);
```
結果會是false，兩個在heap中的地址都是新創立的，故不同

```
        String str1 = new String("abc");
        String str2 = "abc";
        System.out.println(str1 == str2);
```
結果會是false，一個地址在string table，一個在heap

## 常用方法
1. 值比較：equals()
2. 忽略大小寫的值比較：equalsIgnoreCase()

## Iterate a String
利用方法charAt()
```
    String str = "xxxxxxx"
    for (int i = 0; i < str.length(); i++) {
        char c = str.charAt(i);
        System.out.println(c);
    }
```
## 延伸題：Count String Characters
character可轉成ASCII拿來做計算與比較
```
        int upperCount = 0;
        int lowerCount = 0;
        int numberCount = 0;

        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);

            if (c >= 'a' && c <= 'z') {
                lowerCount++;
                
            } else if (c >= 'A' && c <= 'Z') {
                upperCount++;
            } else if ( c >= '0' && c <= '9') {
                numberCount++;
            }
        }
```

## 延伸題：字串串接
將array {1, 2, 3}變成[1, 2, 3]並印出來
```
    public static String arrayToString(int[] array) {

        if (array == null) {
            return "";
        }
        if (array.length == 0) {
            return "[]";
        }

        String result = "[";

        for (int i = 0; i < array.length; i++) {
            if (i == (array.length - 1)) {
                result += array[i];
            } else {
                result += array[i] + ", ";
            }
        }
        result += "]";

        return result;
    }
```
## 延伸題：Reverse a String

### 法1：遞迴
```
    static String reverse(String s){
        // stop the recursion where there is no remainder left and return the string
        if (s.length() < 1) {
            return s;
        }
        /* if not, do the recursion and return
         record the first char of string using charAt(0)
         slice the rest char using substring(1)
         recurse the above process
         e.g.: string -> s_tring -> tring + s -> t_ring + s -> ring + t + s...
         */
        return reverse(s.substring(1)) + s.charAt(0);
    }
```

### 法2：拆解後串接
```
    public static String reverseString(String string) {

        String result = "";
        for (int i = string.length() - 1; i >= 0 ; i--) {
            char c = string.charAt(i);
            result += c;
        }
        return result;
    }
```

## 底層原理說明：
1. 若串接時有變數的參與，代表其底層有新創建物件，此時比較地址的時候會不相同
舉例說明：
```
    public static void main(String[] args) {
        String s1 = "abc";
        String s2 = "ab";
        String s3 = s2 + "c";
        System.out.println(s1 == s3);
    }
```
> 輸出結果為false，因為s3為新創建的物件的地址，s1則是StringTable中abc的地址

2. 若單純只有String的串接，則Java會在compile的時候直接重複使用StringTable的字串
舉例說明：
```
    public static void main(String[] args) {
        String s1 = "abc";
        String s2 = "a" + "b" + "c";
        System.out.println(s1 == s2);
    }
```
> 輸出結果為true，因為兩個地址都指向同一個StringTable中的物件