String 클래스는 char[] 배열을 인스턴스 변수로 갖는 클래스이다.
String 클래스 특징, 메소드 그리고 관련 클래스인 StringBuffer 와 StringBuilder 에 대해 알아보도록 하자.
String 은 변경 불가능한 클래스이다. (Immutable Class)
String a = "a";
String b = "b";
a = a + b; // "ab"
예시를 보면 a 클래스의 문자열이 "a" 에서 "ab" 로 바뀌었다. 변경 불가능한 클래스인 String 이 어떻게 값을 바꾸었을까? 결론부터 말하면 값을 바꾸진 못한다.
a, b 모두 클래스이기 때문에 변수 자체에는 주소값이 저장되어 있다. 해당 주소값에 가보면 문자열 데이터가 저장되어 있다.
a = a+b 에서 두 가지 일이 벌어진다.
- 새로운 메모리 공간에 "ab" 가 저장된다. (그림에서는 주소 0x300)
- a 는 이전에 0x100 주소를 가리켰지만 이제는 새로운 주소 0x300 를 가리키게 된다.
문자열 비교
문자열을 만드는 두가지 방법, 문자열 리터럴을 저장하는 방법과 String 클래스의 생성자를 사용해서 만드는 방법이 있다.
1. 문자열 리터럴을 지정
String str1 = "abc";
String str2 = "abc";
문자열 리터럴은 클래스가 메모리에 로드될 때 자동적으로 미리 생성된다. 따라서 "abc" 가 자동적으로 미리 생성되고 str1과 str2 모두 같은 주소를 가르킨다. 즉 하나의 String 인스턴스 "abc" 를 여러 변수에서 공유한다.
2. String 클래스의 생성자 사용
String str3 = new String("abc");
String str4 = new String("abc");
new 를 통해 메모리 할당이 되기 때문에 str3, str4 모두 새로운 인스턴스를 가르킨다.
JVM 입장에서의 문자열 리터럴
자바 소스파일에 포함된 모든 문자열 리터럴은 컴파일 시에 클래스 파일에 저장된다. 이때 같은 내용의 문자열 리터럴은 한번만 저장되어 하나의 인스턴스를 여러 변수에서 공유한다. 저장되는 공간을 힙 영역 안에 있는 문자열 상수 풀이라고 한다.
class Main {
public static void main(String[] args) {
String str1 = "abc";
String str2 = "abc";
String str3 = new String("abc");
String str4 = new String("abc");
}
}
예시를 살펴보도록 하자.
먼저 str1, str2, str3, str4 모두 지역 변수로 JVM 스택 영역에 저장된다. 그렇다면 String 인스턴스는 메모리가 할당되어 힙 영역에 저장될 것인데 이 관계를 보면 다음과 같다.
문자열 지정을 통해 저장된 변수는 컴파일 시에 문자열 상수 풀에 모든 변수가 공유할 문자열 인스턴스 "abc" 를 문자열 상수 풀에 저장해준다. 문자열 생성자를 이용하여 할당하는 경우 일반 힙 영역에 저장된다.
String 메소드
- int compareTo(String str)
- boolean contains(CharSequence s)
- boolean endsWith(String suffix)
- boolean equalsIgnoreCase(String str) - 대소문자 구분없이 비교
- int indexOf(int ch) - 못 찾으면 -1
- int indexOf(String str) - 못 찾으면 -1
- int indexOf(int ch, int pos) - 지정 위치부터 확인
- int lastIndexOf(int ch) - 못 찾으면 -1
- boolean startsWith(String prefix)
- String.join(구분자, 문자열)
StringBuffer 와 StringBuilder
공통점
- String 클래스가 immutable 한 것과는 달리 StringBuffer 와 StringBuilder 은 mutable하다. 따라서 변경할 때 새로운 메모리 할당 없이 변경이 가능하다는 장점이 있다.
- 기본적으로 디폴트 버퍼 사이즈는 16이다. 이를 넘어서면 다시 버퍼 사이즈 16를 증가시킨 객체를 만들고 문자열을 할당한다.
차이점
- StringBuffer : 멀티쓰레드에 안전(thread-safe) 하도록 동기화 되어있다. 하지만 이 때문에 성능이 많이 떨어진다.
- StringBuilder : StringBuffer와 간전히 같지만 쓰레드 동기화만 빠진 클래스
StringBuilder 메소드
- StringBuilder delete(int start, int end)
- StringBuilder deleteCharAt(int index)
- StringBuilder insert(int pos, ?)
- StringBuilder replace(int start, int end, String str)
- StringBuilder reverse()
- void setCharAt(int index, char ch)
- String substring(int start)
- String substring(int start, int end)
'📗Java' 카테고리의 다른 글
[Java] 자바 가상 머신 (JVM) 과 GC (1) | 2023.09.06 |
---|---|
[Java] 쓰레드 동기화 (0) | 2023.08.29 |
[Java] 예시와 함께 알아보는 추상화 - 추상클래스와 인터페이스 (0) | 2023.07.20 |
[Java] Chained Exception (0) | 2023.07.20 |
[Java] default 메소드는 왜 생겼는가? (0) | 2023.07.19 |