# String 자료형

#### `String` : 문자열 자료형

* 0\~다수의 문자들로 구성
* 쌍따옴표로 둘러쌈
* 이제까지 배운 자료형들과 달리 **참조 자료형**
  * 그러나 특별히 원시값과 유사하게 사용될 수 있음

```java
package sec03.chap05;

public class Ex01 {
    public static void main(String[] args) {
        //  리터럴 방식
        String str1 = "Hello World!";
        String str2 = "안녕하세요 😆 반갑습니다~ 🖐️🖐️🖐️";

        // 빈 문자열 가능
        String str3 = "";

        //  인스턴스 생성 방식
        String str4 = new String("나중에 자세히 배웁니다.");
    }
}

```



* 클래스의 인스턴스
  * 일단, 단순 값 뿐 아니라 특정 기능들을 가진 무언가로 이해할 것
  * 객체지향 섹션에서 상세히 다룸



```java
package sec03.chap05;

public class Ex02 {
    public static void main(String[] args) {

        String hl1 = "Hello";
        String hl2 = "Hello";
        String wld = "World";

        //  리터럴끼리는 == 을 사용하여 비교 가능
        boolean bool1 = hl1 == hl2;
        boolean bool2 = hl1 == wld;

        String hl3 = new String("Hello");
        String hl4 = new String("Hello");
        String hl5 = hl4;

        //  💡 인스턴스와 비교하려면 .equals 메소드를 사용해야 함
        //   특별한 경우가 아니면 문자열은 .equals로 비교할 것
        boolean bool3 = hl3 == hl4;

        boolean bool4 = hl1.equals(hl2);
        boolean bool5 = hl1.equals(hl3);
        boolean bool6 = hl3.equals(hl4);
        boolean bool7 = wld.equals(hl2);

        //  같은 곳을 참조하는 인스턴스들
        boolean bool8 = hl4 == hl5;
    }
}

```

<figure><img src="https://3814826491-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FJyHOwztPxBT3bLpisjCt%2Fuploads%2FrwygNJi0916GL7jLcMo4%2F_%EB%8C%80%EC%A7%80%201.png?alt=media&#x26;token=88c77004-1716-44e2-9be0-7b91aebca66b" alt=""><figcaption></figcaption></figure>

```java
String strVar1 = new String(“신민철”);
String strVar2 = “신민철”;
String strVar3 = “신민철”;
```

<figure><img src="https://3814826491-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FJyHOwztPxBT3bLpisjCt%2Fuploads%2F7cNSpSKD9q8sECqvUKpN%2FScreenshot_37.png?alt=media&#x26;token=998d8c98-5b8d-4136-b697-0028eb4ba34e" alt=""><figcaption></figcaption></figure>

* 리터럴로 생성시: **String constant pool** 이란 곳에 중복 없이 저장됨
  * 같은 문자열이 적힌 리터럴 변수들은 같은 것을 가리킴
* 객체 인스턴트로 생성 시 : 매 번 새로 생성되어 각각 자리를 차지

```java
package sec03.chap05;

public class Ex03 {
    public static void main(String[] args) {

    String str_b1 = "Hello, ";
    String str_b2 = "World!";

    // + 연산자: 이어붙여진 결과를 반환
    String str_b3 = str_b1 + str_b2;


    //  += 연산자:
    //  1. ⭐️ 해당 변수에 문자열을 이어붙임 (부수효과)
    String str_c1 = "나는 아무 생각이 없다. ";
    str_c1 += "왜냐하면 ";
    //  2. 그 결과를 반환
    String str_c2 = str_c1 += "아무 생각이 없기 때문이다.";

    boolean bool_c = (str_c1).equals(str_c2);

    }
}

```



#### 타 자료형간 변환

```java
package sec03.chap05;

public class Ex04 {
    public static void main(String[] args) {
        //  💡 타 자료형으로부터 문자열로 변환
        String str1 = String.valueOf(true);
        String str2 = String.valueOf(false);
        String str3 = String.valueOf(123);
        String str4 = String.valueOf(3.14f);
        String str5 = String.valueOf('가');

        String str6 = true + "";
        String str7 = 123.45 + "";

        String str123 = "123";

        //  문자열을 정수 자료형으로 변환하기
        byte bytNum = Byte.parseByte(str123);
        short srtNum = Short.parseShort(str123);
        int intNum = Integer.parseInt(str123);
        long lngNum = Long.parseLong(str123);


        //  대소문자 무관 'true'일 때 true 반환
        boolean bool1 = Boolean.parseBoolean("TRUE");
        boolean bool2 = Boolean.parseBoolean("true");
        boolean bool3 = Boolean.parseBoolean("T");

        String strA = "A";
        char chr = strA.charAt(0);

        //  ⚠️ 런타임 에러 발생. 하나씩 주석해제해서 테스트
        //  '실행'으로 테스트하거나, 디버그 후 콘솔 탭에서 확인해볼 것

        //byte bytNum2 = Byte.parseByte("12345");
        //int intNum2 = Integer.parseInt("123.45");
        //double dblNum2 = Integer.parseInt("하나");


    }
}

```



#### 이스케이프 표 escape sequence

| 이스케이프 표현 | 대체      |
| -------- | ------- |
| \\"      | 큰따옴표    |
| \’       | 작은따옴표   |
| \n       | 줄바꿈     |
| \t       | 탭       |
| \\\\     | 백슬래시 하나 |

```java
package sec03.chap05;

public class Ex05 {
    public static void main(String[] args) {

//        String str1 = "문자열에 "큰따옴표가" 안 들어가요";
//        String str2 = "엔터도 안 들어가요.
//                "못 믿겠으면 넣어봐.";

        //  실행하여 확인
        String str = "문자열에 \"큰따옴표\"도,\n엔터도 넣을 수 있다고?";
        System.out.println(str);


        String table = "언어\t\t종류\t\t\t\t자료형\nJava\tcompiled\t\t정적\nPython\tinterpreted\t\t동적";
        System.out.println(table);

        char singleQuote = '\'';
        System.out.println(singleQuote);

        String path = "C:\\Document\\MyCodings";
        System.out.println(path);
    }
}

```





## 문자열 메소드

#### 문자열은 **불변** _immutable_

* 문자열 스스로를 변경하는 메소드는 없음 - _”문자열 고쳐 쓰는 거 아니다”_
  * 새 문자열 또는 다른 값을 반환
  * ⚠️ 문자열 변수에 다른 값을 넣을 수 없다는 뜻이 아님

#### ⭐️ 반환값과 인자의 자료형 등을 살펴볼 것

#### 문자열 길이 반환

```java
package sec03.chap06;

public class Ex01 {
    public static void main(String[] args) {
        int int1 = "".length();
        int int2 = "헬로".length();
        int int3 = "Hello".length();
        int int4 = "김수한무 거북이와 두루미".length();
    }
}

```

#### 빈 문자열 여부

```java
package sec03.chap06;

public class Ex02 {
    public static void main(String[] args) {
        String str1 = "";
        String str2 = " \t\n";

        int int1 = str1.length();
        int int2 = str2.length();

        //  💡isEmpty : 문자열의 길이가 0인지 여부
        boolean bool1 = str1.isEmpty();
        boolean bool2 = str2.isEmpty();

        //  💡isBlank : 공백(white space)을 제외한 문자열의 길이가 0인지 여부
        boolean bool3 = str1.isBlank();
        boolean bool4 = str2.isBlank();
    
        String str3 = "\t 에 네 르 기 파!! \n";

        //  💡 trim : 앞뒤의 공백(white space) 제거
        String str4 = str3.trim();

        //  변수 그 자체에 적용하기
        //  - 문자열은 불변 : 변수가 가리키는 종이를 바꾸는 것
        //str3 = str3.trim();
    }
}
```



문자 반환

```java
package sec03.chap06;

public class Ex03 {
    public static void main(String[] args) {
        String str1 = "이거 어디까지 올라가는 거에요?";

        //  💡 charAt : ~번째 문자 반환
        char ch1 = str1.charAt(0);
        char ch2 = str1.charAt(4);

        //  ⭐️ 마지막 문자 얻기
        char ch3 = str1.charAt(str1.length() - 1);
    }
}

```



문자(열)의 위치 반환

```java
	String str2 = "얄리 얄리 얄라셩 얄라리 얄라";

        //  💡 indexOf/lastIndexOf : 일치하는 첫/마지막 문자열의 위치
	//  앞에서부터 카운트해서 int로 반환

        //  두 번째 인자 : ~번째 이후/이전부터 셈
        int int1 = str2.indexOf('얄');
        int int2 = str2.indexOf('얄', 4);

        int  int3 = str2.indexOf("얄라");
        int  int4 = str2.lastIndexOf("얄라");
        int  int5 = str2.lastIndexOf("얄라", 12);

	//  💡 포함되지 않은 문자는 -1 반환
        int int6 = str2.indexOf('욜');
```



값 동일 여부 확인

```java
package sec03.chap06;

public class Ex04 {
    public static void main(String[] args) {
        //  💡 equals : 대소문자 구분하여 비교
        String str_a1 = "Hello World";
        String str_a2 = new String("Hello World");
        String str_a3 = "HELLO WORLD";

        boolean bool_a0 = str_a1 == str_a2;  // ⚠️ 문자열은 이렇게 비교하지 말 것!

        boolean bool_a1 = str_a1.equals(str_a2);
        boolean bool_a2 = str_a1.equals(str_a3);

        //  💡 equalsIgnoreCase : 대소문자 구분하지 않고 비교
        boolean bool_a3 = str_a1.equalsIgnoreCase(str_a3);
        boolean bool_a4 = str_a2.equalsIgnoreCase(str_a3);
        
    }
}

```



포함 여부 확인 / 정규표현식 일치 여부 확인

```java
package sec03.chap06;

public class Ex05 {
    public static void main(String[] args) {

        String str_b1 = "옛날에 호랑이가 한 마리 살았어요.";

        //  💡 contains : 포함 여부
        boolean bool_b1 = str_b1.contains("호랑이");
        boolean bool_b2 = str_b1.contains("나무꾼");

        //  💡 startsWith : (주어진 위치에서) 해당 문자열로 시작 여부
        boolean bool_b3 = str_b1.startsWith("옛날에");
        boolean bool_b4 = str_b1.startsWith("호랑이");
        boolean bool_b5 = str_b1.startsWith("호랑이", 4);

        //  💡 endsWith : 해당 문자열로 끝남 여부
        boolean bool_b6 = str_b1.endsWith("살았어요.");
        boolean bool_b7 = str_b1.endsWith("호랑이");
        
        String emailRegex = "^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$";

        String str_c1 = "yalco@yalco.kr";
        String str_c2 = "yalco.yalco.kr";
        String str_c3 = "yalco@yalco@kr";

        boolean bool_c1 = str_c1.matches(emailRegex);
        boolean bool_c2 = str_c2.matches(emailRegex);
        boolean bool_c3 = str_c3.matches(emailRegex);
        
    }
}

```

### 문자열 비교

```java
package sec03.chap06;

public class Ex06 {
    public static void main(String[] args) {

        String str_a1 = "ABC";
        String str_a2 = "ABCDE";
        String str_a3 = "ABCDEFG";

        //  💡 compareTo : 사전순 비교에 따라 양수 또는 음수 반환

        //  같은 문자열이면 0 반환
        int int_a1 = str_a1.compareTo(str_a1);

        //  시작하는 부분이 같을 때는 글자 길이의 차이 반환
        int int_a2 = str_a1.compareTo(str_a2);
        int int_a3 = str_a1.compareTo(str_a3);
        int int_a4 = str_a2.compareTo(str_a3);
        int int_a5 = str_a3.compareTo(str_a1);

        String str_a4 = "HIJKLMN";

        //  시작하는 부분이 다를 때는 첫 글자의 정수값 차이 반환
        int int_a6 = str_a1.compareTo(str_a4);
        int int_a7 = str_a4.compareTo(str_a3);

        String str_b1 = "abc";
        String str_b2 = "DEF";

        int int_b1 = str_b1.compareTo(str_b2);

        //  💡 compareToIgnoreCase : 대소문자 구분 없이 비교
        int int_b2 = str_b1.compareToIgnoreCase(str_b2);
        
        

    }
}

```



## 대소문자 변환

```java
package sec03.chap06;

public class Ex07 {
    public static void main(String[] args) {
        String str_a1 = "Hello, World!";

        // 💡 toUpperCase / toLowerCase : 모두 대문자/소문자로 변환
        String str_a2 = str_a1.toUpperCase();
        String str_a3 = str_a1.toLowerCase();

        String str_b1 = "Hi! How are you? I'm fine. Thank you!";
        String str_b2 = "how";

        boolean bool_b1 = str_b1.contains(str_b2);

        //  ⭐️ 영문 텍스트에서 대소문자 무관 특정 텍스트 포함 여부 확인시
        boolean bool_b2 = str_b1
                .toUpperCase()
                .contains(str_b2.toUpperCase());

        boolean bool_b3 = str_b1
                .toLowerCase()
                .contains(str_b2.toLowerCase());

    }
}

```

&#x20;\- 유저는 개발자가 상상하지도 못했던 오류들을 만들어낸다.&#x20;



### 이어붙이기

```java
package sec03.chap06;

public class Ex08 {
    public static void main(String[] args) {
        //  💡 concat : 문자열을 뒤로 이어붙임
        String str_a1 = "슉-";
        String str_a2 = "슈슉-";
        String str_a3 = "슈슈슉-";

        String str_a4 = str_a1 + str_a2 + str_a3;

        String str_a5 = str_a1.concat(str_a2);

        //  ⭐️ 메서드 체이닝
        String str_a6 = str_a1
                .concat(str_a2)
                .concat(str_a3)
                .concat(str_a4)
                .concat(str_a5);


        //  ⭐️ + 연산자와의 차이

        String str_b1 = "ABC";

        //  1. concat에는 문자열만 이어붙일 수 있음
        String str_b2 = str_b1 + true + 1 + 2.34 + '가';
        String str_b3 = str_b1
                //  .concat(true)
                //  .concat(1)
                //  .concat(2.34)
                //  .concat('가')
                ;

        //  2. concat은 필요시에만 새 인스턴스 생성 (큰 의미 없음)
        String str_b4 = str_b1 + "";
        String str_b5 = str_b1.concat("");

        int str_b1Hash = System.identityHashCode(str_b1);
        int str_b4Hash = System.identityHashCode(str_b4);
        int str_b5Hash = System.identityHashCode(str_b5);

        //  3. null이 포함될 경우
        String str_c1 = null;

        //  + 연산자는 null과 이어붙이기 가능
        String str_c3 = str_c1 + null + "ABC";

        //  ⚠️ concat은 NullPointerException 발생
        //String str_c4 = str_c1.concat("ABC");
        //String str_c5 = "ABC".concat(str_c1);

    }
}

```

* `+` 연산 : 다중 연산시 메모리 절약
  * ⚠️ 반복 연산 _(이후 배울 `for` 루프 등)_ 에는 무의미
  * 반복 연산시에는 명시적으로 `StringBuilder... append` 사용
* 성능이 중요하다면 이후 배울 `StringBuilder`, `StringBuffer` 등 사용
  * 그렇지 않을 시 상황에 따라 메서드 체이닝 등의 편의를 위해 `concat` 사용



## 반복하기 / 자르기

```java
package sec03.chap06;

public class Ex09 {
    public static void main(String[] args) {
        String str_a1 = "덜컹";

        // 💡 repeat : 문자열을 주어진 정수만큼 반복
        String str_a2 = str_a1.repeat(2);
        String str_a3 = str_a1
                .concat(" ")
                .repeat(3)
                .trim();


        String str_b1 = "대한민국 다 job 구하라 그래";

        //  💡 substring : ~번째 문자부터 (~번째 문자전까지) 잘라서 반환
        String str_b2 = str_b1.substring(7);
        String str_b3 = str_b1.substring(7, 10);
        String str_b4 = str_b1.substring(11, 14);

        String piece1 = "다 ";
        String piece2 = "구하라";
        String str_b5 = str_b1.substring(
                str_b1.indexOf(piece1),
                str_b1.indexOf(piece2) + piece2.length()
        );
    }
}

```



## 치환

```java
        //  💡 replace : 주어진 앞의 문자(열)을 뒤의 문자(열)로 치환
        String str_c1 = "점심에 보쌈집에 가서 수육을 먹었다.";
        String str_c2 = str_c1.replace("보쌈", "중국");

        //  여럿 포함시 모두 치환
        String str_c3 = "밥 좀 먹자, 응? 야, 밥 좀 먹자고 밥 밥 밥";
        String str_c4 = str_c3.replace('밥', '빵');

        // ⭐️ 원본은 바뀌지 않는 점 확인

        //  메서드 체이닝
        String str_d1 = "하여튼 호의가 반복되면 권리인 줄 알아";
        String str_d2 = str_d1
                .replace("하여튼", "아무튼")
                .replace("호의", "호이".repeat(2))
                .replace("권리", "둘리");

        String str_e1 = "02=123.4567_8900";

        //  💡 replaceAll / replaceFirst : ⭐️ 정규표현식 사용 가능
        //  전부 치환 / 첫 번째 일치부분만 치환
        String str_e2 = str_e1
                .replaceAll("[=._]", "-")
                .replaceFirst("[-@#]", ")");
```



## 배열 반환

```java
package sec03.chap06;

public class Ex10 {
    public static void main(String[] args) {
        String str1 = "가나다라마";
        String str2 = "010-1234-5678";
        String str3 = "하나 둘 셋 넷 다섯";

        //  💡 toCharArray : 문자열을 분할하여 문자열의 배열로 반환
        char[] chAry1 = str1.toCharArray();
        char[] chAry2 = str3
                .replace(" ", "")
                .toCharArray();

        //  💡 split : 주어진 기준으로 (~개까지) 분할하여 문자열 배열로 반환
        String[] strAry1 = str1.split("");
        String[] strAry2 = str2.split("-");
        String[] strAry3 = str3.split(" ");
        String[] strAry4 = str3.split(" ", 3);
        
    }
}

```
